Unit test - Good practices
Durgadas Kamath
Principal Architect, Persistent Systems | Speaker?| AWS Community Builder
Unit testing is one of the important steps in the software development process especially in an environment which is driven by Continuous Integration (CI) where every part or unit of code is verified to ensure it behaves as expected.
Unit test is not "Integration test"
Unit tests helps reduce time in the future when the existing code is change .However, automating unit tests for complete code may be a time-consuming process .
It's important to strike a balance between automation and manual testing.
Now, how do we know what is a good unit test and a bad one? How do one go about writing good unit tests?. Even if you’re a brilliant coder with tons of experience, your knowledge and habits won’t automatically lead you to write good unit tests, because it’s a different kind of coding and most people start with unhelpful false assumptions about what unit tests are supposed to achieve.
It's important to have unit test written even before you implement the business logic" . But many about 90% of people implement the logic and then write unit test to support it which is COMPLETELY wrong.
One needs to understand that Unit testing is not about finding bugs or detecting regressions in an application. It's just an process where in you test your units separately. When the application runs in real, these units need to work together. If you have 2 units A and B which are well unit tested, it does not mean that they should work well when integrated. Note, it's just about about testing units of code and not integration of components.
Test Driven Development (TDD) is a design process and not a testing process.
It's about designing software components known as units interactively so that their behavior is specified through unit tests.
Good unit tests are immensely valuable as it documents your design, and makes it easier to refactor and expand your code while retaining a clear overview of each component’s behavior. However, bad unit tests are immensely painful as it doesn't prove anything clearly and can severely inhibit your ability to refactor or alter your code in any way.
Outlining few good unit testing practices:
1. Tests should be isolated i.e able to run independently.
2. Test only one thing in one test case
3. Don't make unnecessary assertions
4. Avoid unnecessary preconditions:
- Avoid having common setup code that runs at the beginning of lots of unrelated tests. Otherwise, it’s unclear what assumptions each test relies on. Sometimes, it may be helpful to share a common code across series of unit tests but you need to make sure that the pre-requisites are actually needed.
5. Name your unit tests clearly and consistently
6. Mock External References
- Mock external references so that when executed it should not depend on external entities such as connection to a database or a configuration file. Mocking external references essentially means that we assume specific data from external services and test only our business logic.
- Another reason for mocking is if there is a connection problem with the external entity, the unit test scripts are bound to fail. So there are two levels of testing being done, one for the external entity and other is the action performed on the data retrieved. Ideally, these should be two different test scripts to identify the bug better.
7. Avoid the Expected Exception Tests
- One needs to avoid these kind of tests : @Test(expected = Exception.class) . This doesn't test what it claims to test . Exception may be thrown from some were else in your code. This is one of the most committed mistakes.
So to summarize, it's important for one to understand what Unit tests are and how to go about writing a good unit tests. Reiterating the statement that Unit tests are not Integration test and successful unit test case result does not indicate that application will run correctly when integrated.
Technical Architect - Product Engineering @FINEOS | Intelligent Insurtech #FINEOS_Cloud #AWS
9 年Nice post Durga :) Just adding to your point 7 - avoid expected exception tests - how about instead of expected exception annotation we use ExpectedException rule (assuming junit) with custom error code matcher with Hamcrest. This will allow to test for your exception with a specific code, message and verify cause of thrown exception. What are your thoughts.