Most development teams will agree that, although they don't like it, unit testing is, in fact, extremely valuable. Despite the many tools that help with manual test creation, creating and maintaining unit tests still requires a lot of manual, time-consuming, often mind-numbing effort before adding business logic to a test. As such, despite having the intentions of great unit testing, development teams typically do the minimal amount of unit testing required, or skip it altogether.
Developers Have Spoken
A recent customer survey revealed, somewhat expectedly, that test creation, mocking/isolation, and maintenance are key issues standing in the way of unit testing success. Figure 1 shows the results of a this survey, showing the top concerns developers are identifying with unit testing in Java.
Figure 1: Survey results show key areas of concern (percentage) that arise from unit testing.
To address these main areas of concern, we can turn to automated software testing technology. Using an automated testing tool that provides not only automated test execution and data collection, but also guided test creation assistance, users can gain the much-needed benefits of automation at test creation time.
Guided unit test creation technology sets up the test framework, instantiates objects, and configures mocks for appropriate objects and method calls used by the method under test. The technology creates regular JUnits, getting all the mundane work done so developers can focus on applying human intelligence and logic to their testing.
Benefits of Unit Testing and Why Developers Still Avoid It
Unit testing is iterative, and in agile processes, unit testing has a good track record of improving project outcomes. And of course it is well-proven that testing earlier in the lifecycle is the best way to detect and remove expensive and time-consuming system-level bugs later on. More specifically, the following are some key benefits of unit testing:
- Providing agility for agile processes: Agile processes depend on efficient, repeatable, and automated test suites in order to ensure that each iteration isn’t bogged down in a “big bang” test cycle. The success of agile and DevOps very much depends on development teams creating test suites that can be run efficiently, as well as testing as much functionality as possible.
- Improved quality and security: Software teams understand that testing is the only way to ensure software is doing what’s required, but teams often fail to do enough testing or do it too late in the development lifecycle. Security, in particular, needs to be built into an application at the earliest stages, so testing for security must be done as early as possible.
- Reducing costs in the long run: Software bugs found in released software can be 1000 times more expensive to fix than during development. Bugs found at early coding stages in unit testing are much cheaper than those found later. Short-term investment in testing automation and unit test infrastructure pays off in better product quality, security, and on-time delivery.
Unfortunately, regardless of these benefits, developers are still struggling with unit testing, despite the desire to achieve better results. These struggles, also illustrated by the survey results above, include the following:
- Test creation is extra work and often tedious: Understandably, unit testing is extra work and is often seen as the least desirable aspect of programming. Creating a comprehensive test suite while trying to maintain project goals and deadlines are two competing pressures for development teams.
- Test maintenance is expensive: Just like code, unit tests require maintenance. Any code change may introduce changes in associated tests. Not only that, tests that fail due to code base modifications might be seemingly unrelated, leading to test suite instability. Extra maintenance creates “double the work” in many developers’ minds.
- Mocking and isolation units under test is difficult and time consuming: It’s critical to isolate units under test, but doing so requires mocking of dependencies, which can be a time-consuming process.
Software development teams must address these problems with test creation, isolation, and maintenance if they want to achieve the benefits of thorough unit testing. Test automation can help, but often adds problems of its own. The real solution is intelligently guided test creation. A guided unit test creation tool provides the assistance needed for test creation and maintenance, while working within the developer’s IDE and leveraging existing test and mocking frameworks.
Reduce Burden with Guided Test Creation
Creating unit tests is tedious and steers attention away from the more interesting parts of a project. The code itself is repetitive and often requires as much effort as the code under test, and on top of that, the unit test code itself requires fixing and debugging, as any code would. Fortunately, unit tests lend themselves well to automation, and tool guidance can great simplify test creation, reduce the amount of debugging and fixing, and collect results and metrics to feed project analytics.
Going beyond the IDE
Many IDEs provide unit test creation wizards for JUnit, for example, but don’t provide “content” to complete the process. Assertions need to be manually defined, and if mocking frameworks are used, a significant amount of manual coding is required. This is where guided test creation comes in by providing real-time, context-aware assistance in the developer’s IDE. With guided unit test creation, the “content” missing from simple skeleton unit tests are quickly and efficiently completed, as the test assistant performs the following:
- Creates test framework, instantiates objects, and configures appropriate mock objects and methods
- Performs runtime analysis of test automation execution to highlight object values that changed during the test and recommend assertions foandr verification of these values.
- Identifies method calls that should be mocked in order to better isolate the code under test
- Detects system resources created but not freed after test completion, potentially creating an unstable test environment
- Collects code coverage and other metrics
To address this, let’s look at an example. Here, Parasoft Jtest’s Unit Test Assistant is invoked with an IDE to create parameterized tests:
The tool creates the following unit test code, at which point the developer completes the parameters as required:
To create test cases for different values of parameters, the test assistant provides a test case wizard:
And you’re off.
Reduce Mocking Complexity
Unit testing implies isolation of the object under test, which requires a fair amount of work if there are many dependencies. Even with mocking frameworks such as Mockito or PowerMock, there is still significant manual coding required. With an automated test assistant tool, you can detect dependencies and automatically fill in details required by the framework.
The tool itself analyzes the code under test, automatically detects dependencies, and makes recommendations to the developer.
For example, here we are executing the following unit test of class IWorkspaceClass:
Dependencies are detected during runtime, and the tool recommends mocking the dependencies that it has found:
Selecting “Mock It” with the tool generates the necessary mocking code with the unit test. Once this code is generated, it can be customized to represent correct logic as required. Automated detection of dependencies and subsequent mocking code creation greatly reduces the amount of manual, and potentially error-prone, coding required to mock objects.
Test Suite Maintenance Reduced Through Automation
Maintenance of test suites overlaps much of the work required for test creation, such as creating new tests, modifying tests to suit the underlying logic, mocking dependencies, test execution, and verification. Getting assistance from the Unit Test Assistant during test maintenance is just as valuable as during creation, as it provides updated feedback on runtime analysis results collected during test execution. For example, a new dependency in an object under test is detected at runtime and the tool prompts the developer with how to deal with it.
Equally critical during this phase is ensuring that the assertions are still valid. The Unit Test Assistant provides recommendations that can detect changes in the code and update assertions to reflect new business logic.
Maximizing the Benefit of Existing Tools
Java developers that are already unit testing are likely using JUnit, and possibly an assertion framework for their project, such as Mockito or PowerMock. Test automation tools need to leverage these existing tools, since replacing an existing investment in unit testing would eliminate any cost and time benefit. Jtest's Unit Test Assistant integrates seamlessly with these existing tools, which is critical.
Unit testing has clear benefits, and although most development teams realize this, many are stymied by the effort of creating and maintaining tests. The guided unit test creation technology provided in Jtest removes these roadblocks, and automates the mundane aspects of unit testing, including creation, isolation, mocking, and maintenance. To accelerate adoption, Jtest leverages the development team’s existing investment in test and mocking frameworks, and gives back time to the developer while bringing quality back to the product.