Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Is the unit test worth writing about?


Jun 01, 2021 Article blog


Table of contents


As a programmer, unit tests should be heard of, but many students have not used them, and there may be some misunderstandings about unit tests, such as:

  • Writing unit tests takes more time, I write product code every day to work overtime, where to write tests;

  • Writing unit tests is not very profitable, not the same bug;

  • Writing unit tests is burdensome, changing the structure of the product code, and having to change the test code.

Try to answer these questions first.

Writing unit tests takes more time, which is not an accurate description. T o be precise, writing unit tests takes more "time to write code", which is nothing to say, after all, to write more test code. B ut a programmer, when doing a requirement, spends little time writing code. Y ou have to take care of the logic of the previous code, design classes and methods, and then write the code, write the manual test, there may be bug to go to debug then fix, and then test. " The time it takes to actually write code is actually very small". While unit testing may take up more time writing code, it can help you reduce other times, "and will make you spend less time doing this."

Is there a bug for writing unit bug O f course, we can't do a real bug free but unit tests are written to significantly reduce the number of bug B ecause the cost of writing unit tests to discover bug is very low, it can detect bug during the development phase, and it can test the conditions of many boundaries. B ut if you "have misconceptions about demand and business", which unit tests can't solve, bug will naturally arise. I n other words, the benefits of unit testing go far beyond finding bug they also have the ability to "code documentation" and the existence of a "refactored safety net". It can even help you "manage your needs" and "design code".

Changing the product code requires maintaining the corresponding test code, which does incur additional costs. H owever, with the editor's "refactoring function", it is easier to modify the need to modify the place in bulk, in fact, the cost is not as great as imagined. A nd after refactoring, run the unit test again to see which hangs up, can double-check you change the product code there is no problem. If we look at unit tests as "documentation of product code", we are probably more receptive to the cost of this maintenance.

Why do I need unit tests?

As mentioned earlier, unit testing has many functions. P ersonally, I think unit testing is most useful for "code documentation" and "refactoring the safety net." A fter all, the long process of software development, there is no need to repair and modify. If there is not enough testing, change a piece of code is like in the discharge of mines, after the change of heart is always playing drums, before going online need to worship God in silence, for fear of triggering what bug

But if there are enough tests (not just unit tests), you can run through the tests after you've changed the code to see which ones are hanging up, if they're caused by your own changes, and how to fix the tests. So there's a lot of bottom in my heart.

You know, the code is written for people to see. Testing is more friendly than product code because it's simple, straightforward, and described from the user's perspective, so if you want to understand what a piece of product code has, it's more intuitive and comfortable to see its unit tests.

Many teams do testing, but most of the testing work is done after development, with dedicated testing students taking charge of end-to-end testing or API testing. I n fact, end-to-end testing costs are very large, especially for some boundary conditions, and constructing data and scenarios can be cumbersome. And once a bug is discovered, it takes a lot of time to communicate, modify, commit, deploy.

The biggest advantage of unit testing is "low cost", want to test each branch of product code is relatively easy, and unit testing is generally the development students write their own, can use the smallest time to find bug with the lowest cost to modify bug

What is unit testing?

Test the pyramid

Not all tests are unit tests, but they are divided into many kinds. The industry's more widely disseminated "test pyramids" describe their differences and relationships:

 Is the unit test worth writing about?1

From the test pyramid model, the more underlying the test, the wider the coverage and lower the cost. Unit tests are at the lowest end of the test pyramid and are the basis of the entire test pyramid.

Of course, the test pyramid does not have to be only three layers, there may be other tests in the middle, such as "contract testing" and so on.

Features of unit testing

Unit tests, like its name, are small enough, fast enough, and dependency-free. U nit tests measure only the logic of the part of the product code you want to test, and a unit test should measure only a simple business logic. I n general, running a unit test is fast, basically between a few milliseconds and dozens of milliseconds. If you have dependent classes, you can mock other classes to eliminate external dependencies.

What's not unit testing?

Many students tend to confuse other tests with unit tests, most often by starting integration tests in the Spring context. For example, using @SpringBootTest annotations can start Spring context, which tests the ability to rely on Spring features such as normal injection, but running it at once takes a lot of time (because you want to start the Spring context) and is not really "unit testing" because it relies on Spring framework.

How to write unit tests

So how exactly do you write unit tests? W e have a methodology called "TDD" (test-driven development) in our industry. A t the heart of TDD is the word "driver", whose philosophy is to drive product code from a test perspective. In the test pyramid, unit testing is most relevant to developers, so "testing" here generally refers to unit testing.

TDD is roughly divided into these steps:

  1. Clarify your needs

  1. Design the out-of-and-in parameters of classes and methods

  1. Write test code

  1. Drive out the product code

  1. Refactor, loop 3-5 steps.

The first step is to clarify the requirements, because only by clarifying the requirements can we ensure that the code we drive with TDD is consistent with business expectations. T he second step is the process of designing classes and methods, also known as Task List T his step can design the relationship between the class and the class, and the method's arguments and in-references. In fact, do not use TDD will also have the first two steps, but the use of TDD can help you better from a business perspective, first design the design of everything, avoid writing directly on the code, write half of the time feel wrong, and then change.

Steps 3-5 are actually a circular process. B ecause just started writing code may not pay too much attention to the format, style, performance of the code, write it more quickly, let the test pass. After the test passes, you can go back and refactor the previously written code, refactor it, and run through all the unit tests to see if there are pending unit tests to detect whether the refactoring has an impact on the expected input and output.

The structure of the unit test

A complete unit test should be divided into four parts:

  1. Declarations and parameters

  1. Prepare to enter the ginseng and mock

  1. Call the product code

  1. Validation, also known as assertion

Java case, there are several unit test frameworks, the most popular of which should be JUnit and TestNG T he author uses JUnit a little more, and JUnit uses @Test annotations to declare a test in a method. The latest version of JUnit is JUnit 5 JUnit 5 has made a lot of improvements in parametric testing compared to the previous version, so that we don't have to write many highly similar test methods (for JUnit 5 parametric tests, you can view official documents, as well as corresponding Chinese translations, which are easy to read).

In general, method names need to be as readable as possible, which may be longer, but clearly state the intent of the test, such as:

@Test void shouldReturn5WhenCalculateSumGiven2And3() {}


@Test
void should_return_5_when_calculate_sum_given_2_and_3() {}

Whether to use hump nomenclase or underline, according to their own team's specifications, try to be consistent with all test styles. (Individuals prefer to underline it)

References are generally basic types or POJO objects, and some parameters can be drawn into variables that may be used later in the validation phase.

If the product code has an external dependency, you need to use mock to eliminate the external dependency. Common Mock frameworks include EasyMock "Mockito" and so on, so you can compare the differences between the mock frames and choose a suitable one.

Many students just started to write unit tests can not understand why the need for mock think mock is more troublesome, even a little more feeling of this. I n fact, the meaning of mock is that you "can guarantee that your test only tests the part of code that you want to test." So if the test doesn't pass, you'll know that there must be a problem with the method you're testing, and it can't be an external dependency problem, so that you can make a real "unit" that guarantees that each test is small enough and pure enough.

When you are ready to enter the parameters and mock you explicitly call the method you want to measure, which is usually a simple line.

Finally, validation, verification is divided into several kinds, the most commonly used is to verify that the parameters are in line with their expectations. B order conditions such as exceptions are also sometimes validated. Test frameworks such as JUnit basically bring their own verification functions, but API are relatively simple, personal feeling is not particularly useful, recommended to use "AssertJ", powerful, API is more comfortable to use.

Let's take an example:

@Test void shouldReturnUserWithOrgInfoWhenLoginWithUserId() { String userId = "userId"; S tring orgId = "orgId"; U ser user = UserFactory.getUser(userId); O rg org = OrgFactory.getOrg(orgId); given(orgService.getOrgById(orgId)).willReturn(org);

    
    UserInfo userInfo = userService.login(userId);

    
    assertEquals(org, userInfo.getOrg());
}

Unit testing FAQs

Let's talk about some of the common problems with unit testing.

Write a test first or a product code first?

That's all right. A lthough there is a saying that TDD recommends writing tests before writing implementations. B ut many of the students who are just starting to write unit tests aren't used to it. W riting tests first has the benefit of having you think from a business perspective when designing your code, rather than from a code implementation perspective. You can try to write tests before you write implementations, and experience this feeling.

Does writing unit tests take a lot of extra time?

This has actually been discussed at the beginning of the article. W riting unit tests does take more time to "write code," but overall, it can shorten the entire requirements development cycle. So writing unit tests is a "good deal."

What code requires unit testing most?

Unconfident code, logical complex code, important code. For example, tool classes, Service layers for three-tier architectures, aggregate roots for DDD and domain services, these should all write enough unit tests.

Too much trouble constructing in-reference objects?

It is cumbersome to construct a suitable parameter object, especially if some objects have a very large number of parameters, if each test has to be constructed from scratch, it will make the test code become very bloated, poor readability. F actory classes can be used to mass produce objects at this time. T his factory class is placed in the test catalog and does not affect the production code. In the previous example, UserFactory is a factory class for a User object.

What is the return value void test for?

The return value is void indicating that the method does not have a parameter, and that there must be some behavior within the method, which may be "changed the value of the internal property" or "the method that called an external class".

If you change an internal value, you can assert it by the object's get parameter. T his is a problem with the domain model after DDD is used, because it is possible that the product code would not have exposed get method, but because of the testing needs, the get method of the internal properties was exposed. A lthough you can also get the value of an internal property using reflection, it is not necessary. It's better to weigh the pros and cons, or to expose the get approach to the domain model.

If you are calling an external method, you can use verify to verify that a method has been called, and capture to validate the arguments that called another method. This also verifies that the product code is working as expected.

How about the static method?

static method is not good for mock and requires a special mock framework. L ike PowerMock JMockit I n general, many of the methods of Utils class are static and we spend a lot of time in the class LocalDateTime getting the current time, which is also static This time you need to use a special mock frame to mock

How do multithreaded tests?

Multithreaded is also difficult to test. If the program is simple, you can use multithreaded tool classes such as Sleep or CountDownLatch to aid the test, wait for all threads to run, and then verify uniformly.

If the program is relatively complex, you need to use a specialized multithreaded testing framework, such as tempus-fugit Thread Weaver MultithreadedTC and OpenJDK jcstress project.

For specific framework use, you'll have time to write an introduction to a commonly used annotation later. I n fact, the official documents are written, we write a few examples according to the official website will be. T he more recommended base plan is junit 5 + mockito + assertj With regard static method and the multithreaded testing framework, it's okay to learn when you need it.

To learn more about testing, take a look at the tutorial:

Software testing: https://www.w3cschool.cn/software_testing/

Source: www.toutiao.com/a6856755990545891848/