In software development projects, starting the testing process as early as possible in the coding phase is advantageous because bugs can be found and fixed quickly and cheaply. Depending on the company and project, of course, testers are expected to review and approve functional documents, and after approval, testers go on to design tests and prepare charters or scripts for the functional testing stage, once the software is “ready.”
However, very often in my experience, unit tests have been regarded as the development’s team responsibility, and—regrettably, for numerous reasons—the unit tests are not done. The main reason is that developers think there is not enough time to write and execute unit tests.
I understand that development teams are under big time constraints to code and move on to the next feature, and consequently, the functionalities agreed on in the documents often are not possible. Poorly documented or even undocumented changes are passed on to the testing team. At this point the testers are under time pressures to change and execute their tests to explore how the system now works.
As a test manager, I have asked if there is a way to solve these problems that appear in the late stages of development.
Getting Testers Involved Earlier
One solution that has worked well for my teams is for testers to take an active role in the late stages of coding, or even earlier if possible, by being responsible for unit testing. Whether the entire unit testing effort is taken over by the test team or testers just sit in as part of the development depends on the project, but I have seen positive results when testers take responsibility for writing and executing unit tests.
A further advantage of including testers in unit testing is that, by observing the code and creating unit testing assertions and verifications, testers learn the flow and function of the code and can use this knowledge in later test design. The testing team can and should be included in code reviews, but creating and executing unit and integration tests gets testers interacting with the code even earlier in the development process. By doing so, additional tests can find issues that the developers who wrote the code would not expect.
Testers who create and execute unit tests do so not with the developer mentality—that is, wishing to show that tests pass and that the code therefore “works”—but to write multiple tests that have finding bugs as their main purpose. Also, by tasking unit and integration testing to the test team, developers are freed to continue developing other features, reducing the time of the development stage.
Streamlining the Unit Testing Process
As I see the future of testing, I think that due to the rise of DevOps, agile, and continuous integration, testers with good coding or scripting abilities (the language depends on the tester) will be necessary.
The role of the software tester has become more complicated. No longer can we just read requirements, create and execute cases, and write bug reports. To thrive in the increasingly rapid world of software testing, we need to be able to understand and write code. A great start is to learn to write unit test cases.
I once worked on a project to test the website of a large telecommunications company. We were falling behind schedule, but luckily, we had an open-minded development manager who had no problem granting code access to a small group of technically minded, Java-educated, and, at that time, underworked testers.
Rather than getting a developer outside the project who did not know any of the project code to create the unit tests, I thought it would be better for the testers to take responsibility for unit testing. In my view, for the same reason that code reviews are done by someone other than the coder, developers need to let an independent party test their software, whether it is for functional or unit testing. Our experimental test-driven unit-testing project was allowed to proceed.
Our development team used the unit testing framework JUnit, which works with Java and helped influence test-driven development. We figured with some coaching from the developers, we could create our own tester-driven unit testing practice.
In addition to letting the testers review the code and the technical specifications for the new features, the developers sat with the testers and ran through the code in detail, explaining which areas required unit testing with JUnit. After these areas were tested in isolation and appeared stable, larger integration tests were created and executed to see how the separate units functioned as a whole.
As the JUnit test effort continued, we began to see a different style of tester-driven unit testing emerge. As opposed to developer-created unit tests, where a short series of assertions are made that confirm expected results, our testers included boundary analysis and equivalence partition-style tests with JUnit as much as possible. The integration-testing phase provided more opportunities to run these kinds of tests, with the result that bugs were found and fixed quickly and easily.
There were other benefits of tester-driven unit testing, too. The testers finally knew what was happening almost as soon as the code was written. The development team was free to code other features as well, and they could easily explain the new features by showing testers the code directly, without having to revise documents that then needed additional rounds of reading and approval. And the functional testing phase was reduced because of the number of bugs that were found and fixed earlier.
Becoming involved in unit and integration testing gives testers a great incentive to further enhance their development skills. There was much more interaction between developers and testers than in previous releases, and this cooperation led to more knowledge gain for the testers of the code and features. From this project, I saw how tester-driven unit and integration testing helped break down barriers between developers and testers, making testers more a part of the development process and increasing the collaboration between teams.