We have been testing our code ever since we've written it. It's an age-old paradigm to check the quality of software. As tools advance to enable us to ship products faster and better, our expectations rise too. In the world of agile development, we tend to focus more on the number of features that we can create (a.k.a. velocity) than an occasional bug.
A code's quality (something highly subjective, in my opinion) can't alone be determined by the number of bugs present - it depends on several other factors too. Technical Debt (bad code), if left unchecked, can have very disastrous consequences in the long run. But for this article, we'll stick with testing.
While there are many ways of testing code, I will discuss the ones that are prevalent in today's era, which are:
TLD - Test Last Development (a.k.a. Manual Testing): test after the code is written manually (Tested by a QA, not the developer)
Automated Testing - Write Automated Tests that can be executed against the code (not by the developer)
TDD - Test Driven Development, write test cases before code is written (the developer writes both)
Initially, most of the software would be created with waterfall models, i.e., your requirements would be gathered, analyzed, and frozen. The project would be divided up into milestones, and any change to the input requirements would need (usually expensive) change requests. This enabled managers to manage the work better; they would dice and slice the work and distribute it within the team.
But as we know, bugs have been around since the day software was written. Thus came into existence:
As to how most code is still tested today, manual QA (Quality Analyst) plays a vital role in today's era and will continue to do so. There isn't any way that we can completely do away with it.
This form of testing (also known as traditional testing) is done by a different set of eyes than the one who wrote the code. This allows for a different perspective since we all know how good developers are at finding their bugs. Checking stuff manually is more important in frontend aspects of a project such as Web or Mobile to make sure it works correctly on different browsers and mobile devices.
Because developers in such processes were not made an integral part of the planning process, somewhere they did not take full responsibility for the code that they would write.
While this wasn't a significant overhead at first, as software grew more complicated - so did time involved in testing. This called out for ways to automate the process of testing. There, I think, people saw two ways out: Automation Testing and Test-Driven Development (TDD).
When QAs got more efficient with using tools to track and monitor issues, they still had to do a lot of regression testing (testing everything) whenever there was a significant deployment or feature release.
This led to a lot of time inefficiency, and a feeling of not doing productive work (because of its redundancy). Thus testers started writing code to automate the tests they would typically do manually - and they still do.
But along came Agile, which changed the way people shipped code. Today, everyone seeks to go agile because they want to release products faster than ever before. This led to savings in terms of time and, therefore, costs.
TDD is a way of development in which developers write automated tests before they set out to write the code for the same. You could summarize the same in the following steps:
Understand Requirements/Stories and write Test Cases
Run the test cases (also called as a Test Suite) and watch them fail (The test must fail since it shows that scenario isn't dealt with)
Write code to make the test case pass
Re-run the test suite and make sure (read hope) that all the test cases pass
Refactor your code to remove redundant code
With TDD, the responsibility shifted back to the developer to make sure that the code performed as expected. The QA's responsibility shifted from just testing the product to helping write more test cases which the developer would have to work on
Ideally, with TDD, the role of the QA was made redundant, but an important thing was left out - perspective. Because people find it difficult to find holes in their software, we needed a second set of eyes to make sure everything was working smoothly.
Another consequence of writing TDD code was that the code had to be loosely couped for it to be tested throughly. This forced the developer to write code that was better separated - not from a habit, but compulsion.
Therefore, in Agile, a balance was stricken - while developers continued to write code in TDD - it didn't eliminate manual QA, it reduced dependency on it. At SoluteLabs, we follow the same - TDD with manual QA.
There are many other areas where testing can be done and is needed. Still, for most parts, while developing products for startups and enterprises, our focus has always been to ship as fast as possible with the highest standards in code quality.
Our experience with BDD is that it takes too much time, and with requirements changing often, it's not worth the investment.