What is the UT?
UT (Unit Test) is a Unit Test
What is UT worth?
Most developers don’t like writing UT for several reasons:
- Product manager urges progress every day, which has no time to write UT
- UT is testing your own code, self-testing? What’s the point of QA?
- Does self-testing detect bugs? Are based on their own thinking, like the exam to finish the first time, the second time to check the same, basic check what things
- UT maintenance costs are too high and the input-output ratio is too low
- Can’t write UT
In short, there are countless reasons not to write UT. As a rookie who has worked for less than three years, I have experienced it deeply. Previously, when reviewing work, the team’s “UT” was focused on the server side of RPC.
Why the double quotes? Since there is no page for RPC server to function test, it is too cumbersome to deploy to test environment, so you can only write UT. In this case I think it’s more appropriate to call it “verification”. Verification is not the same as testing. Validation usually only writes whether the main logic passes, and there is a Case, and there is no Assert, there is system.out.
I did testing during my internship, and I knew a testing model at that time. The diagram below:
The graph means that the tests performed better as you go down, and worse as you go up. In other words, functional testing is the least effective form of testing that most companies do today. Also, there is a scene in QA: everyone knows that functional testing is not technical, so how do you make yourself stand out? The answer: automated testing. The reality is that few companies can do a good job of automated testing, the industry does better Baidu is one.
So why are automated tests so hard to do? In this model, the higher up the black box, the more difficult automated testing becomes. The flip side of that is the automated testing gets easier as you go down, right? Yes, UT is actually the easiest and most effective automated test to implement. So in many companies there is a scene where QA writes UT.
The reasons can be summed up in two: developers don’t want to write UT, and QA wants to automate testing to free themselves. The above model only theoretically indicates that UT has great value, but is it really so? I just want to say that the value of UT will be realized only when the benefits of UT are truly tasted.
Unit Test & Intergration Test
The line between unit testing and integration testing is also, I believe, unclear for most development. I understand that unit testing is too abstract for the smallest unit of business logic. Physically, it can be simply understood as a method of a class, which can be either public or private. A unit test should not contain the logic of external dependencies, but rather integration tests.
That is the heart of the problem.
An interface implementation of a service may depend on many third parties:
1. Other local services
2. The dao calls
3. The RPC calls
4. Microservice invocation.
The diagram below:
That is to say that your unit tests really invoke external dependencies that are integration tests. This is actually quite common, right? Let’s start with how to integrate tests in this case.
Local Integration Test
Local integration testing means not relying on other processes. Service depends on other local services or DAOs. Before we talk about how to integrate tests, let’s take a look at the test model. Testing consists of three main parts: 1. Data preparation 2. Logic execution 3. Output verification.
Step 1: Data preparation
In local integration testing, the data source basically comes from the DAO, and the DAO comes from SQL. Before executing a case, execute some SQL scripts and use memory databases such as H2. Do not rely on the DB of your company’s test environment.
The following is a case using the Spring-test framework. We can prepare all the data we need before the case is executed. After the case is executed, we can execute the clean.sql script to clean up the dirty data. It is also important to note that the execution environment of a case is completely independent of each other.
Step 2: The simplest logic to execute is to call the method we tested
Step 3: Verify
Integration testing typically involves interface validation of service calls or DAOs.
An example is integration testing for CRUD operations
- Calling C interface
- Call the R interface to verify that C succeeded
- Call U interface
- Call the R interface to verify that U succeeded
- Call D interface
- Call the R interface to verify that D succeeded
Remote Integration Test
Suppose we have a Service implementation that depends on some RPC Service
Step 1: Data preparation
Running into someone else’s database and inserting a few pieces of data? Or negotiate with the Owner of PRC Service to build a test environment for us to test? Some companies do have a dedicated automated test environment, so even if there is a test environment, how to achieve a variety of case scenarios, third-party services to return data to us? It hurts to think about it.
Step 2: Implement methods
Let’s say we successfully solve the problem in step 1, and everyone is happy. Now for step 2, suppose that our service calls another RPC Service and creates a lot of data, runs countless cases, and results in…. How do I clean up the dirty data in the database corresponding to the RPC Service? And would they dare to delete data at will? It hurts to think about it.
Step 3: Output validation
Let’s say we solve the problem in step 2 happily. Now for step 3, suppose that the final output of our method execution is to create an order, which of course calls the order Service interface. How do we verify that the order was successfully created? Perhaps this can be verified by calling the order Service interface to query the order. Obviously most of the time it’s not that perfect. It hurts to think about it. Based on the above analysis, Local Integration Test is feasible, while Remote Integration Test is basically not. So is there any solution? The answer is Mock
- Step 1: The Mock RPC Service returns whatever data it wants
- Step 2: Mock the Mock interface as many times as you want
- Step 3: This will be clear after unit testing
Unit Test
We talked about mocks to solve the problem of external dependencies, and there are many open source frameworks for mocks such as Mockito. If we can mock third-party remote dependencies, why not mock daOs and local services? That’s right, mock out all external dependencies, unit tests. Because we only care about the business logic of the method under test, which is the truly cohesive unit of logic. The diagram below:
The benefits are as follows:
- There’s no data you can’t Mock, all return Mock objects
- Exception handling code in your code can also be made to throw exceptions through a mock interface
- No dirty data is generated
- Running case is faster because you don’t have to start the entire project, which is equivalent to the Main method
Some would say, mock and test your balls.
This is the understanding of unit tests. Unit tests should only test the business logic of the target method. Daos and other services should be tested in their own unit tests. With dependent third parties, we should trust them to do exactly what we expect. It’s hard to understand, isn’t it?
Just a couple of examples
Example 1: The end of the method is to execute the DAO create operation, so how to verify?
What we should verify is:
- The DAO’s create method is called
- The number of calls is correct
- The call parameters are also correct
Yes, as long as these three validations pass, then the case execution passes. Because we trust the DAO’s create operation to do exactly what we expect, as long as we call it the right number of times and the parameters are correct.
The correctness of dao execution is guaranteed during unit testing of that DAO. In Remote Integration Test, the third step is the same. We should verify that the RPC interface is called and the number of times and parameters are correct, then our case is considered to be passed. As for whether the RPC server performs correctly is their business, it is not our concern. The Verify interface of the Mockito framework does just that. If you understand the above, then you will understand that UT is no longer so difficult to write.
When to use unit testing and when to use integration testing?
In my practice, I found that simple business, such as CRUD thin service, is more suitable for integration testing. The following situations are appropriate for unit testing:
- Util class
- Methods that contain remote calls
- A method with little input and complex business logic
- Methods that require exception handling
How detailed is the case?
This problem is also more classic, a method if all paths are covered, then have to write a lot of case, really tiring. My suggestion is two principles: 1. Core logic, error-prone logic must be covered 2. On your own time. There is no need to write too much, after all, case maintenance costs are high, the business logic changes, the case has to change.
conclusion
I am currently engaged in open source project (Apollo(Configuration Center) research and development. Open source project has relatively higher requirements on code quality, and UT is of course a very important part. At the beginning, I could not write UT, and of course, I did not attach importance to UT.
Eldest brother’s code UT coverage rate is very high, holding a responsible attitude to open source slowly accept and learn UT, to later taste several sweet, found UT is really practical, high value, but it is a pity that UT is ignored by most of the development. Of course, my understanding and practice of UT are not enough, so I still need to continue to practice the model.
One last word: when you finish developing features, running UT, and you can safely go online, your UT will be successful.
Recent hot articles recommended:
1.1,000+ Java Interview Questions and Answers (2021)
2. Don’t use if/ else on full screen again, try strategy mode, it smells good!!
3. Oh, my gosh! What new syntax is xx ≠ null in Java?
4.Spring Boot 2.5 is a blockbuster release, and dark mode is exploding!
5. “Java Development Manual (Songshan version)” the latest release, quick download!
Feel good, don’t forget to click on + forward oh!