Go Language Unit Testing

Source: Internet
Author: User

Go Language Unit Testing

The Go language attaches great importance to unit testing, not to mention the background of other authors, such as open-source libraries and third-party support, there are two points that I have the confidence that the Go language attaches importance to unit testing:

  1. Complete unit tests of the Go language source code and built-in Libraries
  2. Go language comes with unit test commands

From these two points, I think testing plays a very important role in the Go language, so in this article, I also try to talk about something about the Go language unit testing.

Write the Go unit test code

The test method of Go looks relatively low. It depends on the commandgo testAnd some usablego testWrite conventions for running test functions. However, I think this is the so-called Go style. Since using Go, I feel that the Go language is a language that keeps the C Programming habits.

First of all, in order to start this article, I will write a simple function as an example to be tested later. However, considering that we may want to talk about some more complex content later, in this example, I have some things that can be changed. You can choose to see:

Bytes

This example is so simple: Name this file as main. go, and then we should write the test code. You can place the file of the test code at will,packageYou can also write it as needed. However, the file name must end with _ test. Therefore, I will name it main_test.go.

Note the following points when writing test functions:

  1. Each test file must end with _ test. go. Otherwisego testTest files cannot be found
  2. Each test file must be imported into the testing package
  3. The function Test function must start with Test, and then generally the name of the Test function. This is not mandatory.

Based on these conditions, we can write a test file:

Bytes

After the test file is written, we should execute the test. Open the command line tool and press this command:go test main_test.go main.go -v -cover

Then we should wait for the test result. Here we add two parameters:-vAnd-coverIf no parameter is added, you will find that only the simple prompt of Test Pass is displayed, but you cannot see the specific prompt that we have added the parameter:

=== RUN   TestAdd--- PASS: TestAdd (0.00s)PASScoverage: 50.0% of statementsok      command-line-arguments  0.008s
Table-based testing

In the Go language, there is a common test routine called table-based testing. The core of the test is that we need to address different scenarios, in fact, different inputs and outputs are used to verify a function. For exampleAddFunction, we need to verify many features, such:

  • Are the two positive numbers correctly added?
  • Are the two negative numbers correctly added?
  • Is a positive number followed by a negative number correct?
  • Is the number 0 correct?

Then, we can use the table-based test method. The code can be written as follows:

Bytes

Mock dependency

The tests described above are relatively simple. If the functions are simple, we can directly specify the input and check whether the output meets expectations. In this way, we can simply write the unit test. However, sometimes, due to the complexity of the business logic, the functional code is not so direct, and many other components are often mixed, which brings great trouble to our testing work, here I will list several common dependencies:

  • Component dependency
  • Function dependency

Component dependencies and function dependencies are two common dependencies. However, these two dependencies can also be extended. They may come from components/functions compiled by ourselves, it may also be written by someone else. However, we will make some analysis on these situations.

Component dependency Processing

When developing projects using the Go language, we should often leave the component modules. Since the components and modules are removed, the dependencies of components are inseparable for a long time. Since there is dependency, during the test, we often want to block the impact of the dependent components to better test the details of the existing code. Or, we want to test the existing code according to our own testing objectives, controls the behavior of dependent components. However, if we still want to control the behavior of dependent components by controlling input and output, it is still difficult. Therefore, in this case, we generally consider passing in a Stub component to control the behavior of dependent components.

For example, for common operations on the Service layer and DAO layer, after the Service finishes processing the logic, it is handed over to the DAO layer for persistence, or you need to call the DAO layer to obtain some necessary data from durability. during testing, we often do not want to be persistent or obtain data from durability, then some Mock will be performed on the DAO layer. First, a running example is provided:

Bytes

Here we want to test the correctness of the Service, but do not want to really persist the DAO, so at this time we will create a Stub and then provide it to the Service. At the same time, we can also operate the DAO behavior to achieve the running effect, for example:

Bytes

In this way, we can test the login successful code. The login successful code is tested. We also want to test the Login Failed code, which is also very simple. Just modify it:

Bytes

Here we have slightly changed the test code. We can find that we can control the output of Stub by modifying a variable to test different functions, this solves the component dependency problem.

Function dependency

Function dependencies are more troublesome than component dependencies, because we can see that we can pass Stub for component dependencies, so that we can control Stub behavior at will, but the function doesn't work. Here we can't pass the function in, because the function is imported. This is the problem. Because the function is imported, it can be understood that the function is global. In this case, why don't we modify the function? What does it mean? Let's first look at the normal business example:

Bytes

Here, I want to express that we need to log on first, and then we can reply to the message after logging on. Here, our login logic is simple,, in the actual business, the login logic here may be designed to access the database, etc. We hope that we will not go through the real logic, but control it by ourselves.Login.

First, analyze our UT purpose. Our purpose is to testReplyFunction, we expect to beLoginSuccessful, thenReplyIt should also be successful; ifLoginFailed, thenReplyIt should also fail. This test conclusion should not beLoginAffected, timely and laterLoginIf the logic is modified, we should also use this logic and it will not be affected, so we can write UT as follows:

Bytes

Here we can see that we modifiedLoginThe code of this function to controlLoginFunction return value, so that we can test whether the logic of the code we write is correct.

Some people may find that the code in the second function dependency has a special point, that is, the functionLoginIt is a variable. Why should I use a function variable? Can't I use a function directly? This is indeed a bit of trouble, because if we use a direct function, we don't have to assign a value, so we can't modify it. If the code is not written by ourselves, but the code of other colleagues, the problem will be high. In this case, what can we do?

There is an article in Reference: Mocking functions in Go introduces a method, that is, assigning the referenced function to a function variable and then using it to achieve the same effect.

Third-party library

In the previous introduction, we all re-wrote a Stub class, but at the same time the problem was exposed, which was complicated and cumbersome to write, so there are some third-party libraries to help us compile these things. Gomock is one of them. Here we will briefly demonstrate some functions of GoMock.

Gomock has two components: gomock and mockgen. Mockgen caninterfaceGenerate the corresponding Stub object. For example, we mentioned DAO. Because our DAO Interface has been written, we can easily generate StubDao by using the following command:

$ mockgen -source=main.go > mock_dao.go

Then let's take a look at the mock_dao.go content:

Bytes

We can find that both functions are implementedReadAllAndSaveDataBut at the same time, we also found that the generated DAO is much more complex than we expected. As to why the medicine is so complex, let's look at the next use. Now that we have DAO, the next step is to control the output of DAO.

Bytes

Here we can see that using gomock makes the control output easier. Previously, we needed to control the output by using the variable, but it is very convenient to use it here:

d.EXPECT().FuncXXX.Return(xxxx)

It is really convenient to specify what results should be returned by the function. At the same time, it also saves us time to write MockClass by ourselves. This is worth a try.

Summary

OK. This article is about so much about Go UT. Here we introduce the compiling routine of Go unit testing and the processing of some common scenarios in our projects, finally, we introduced a third library to speed up UT writing. In my other article: from an open-source project perspective, I once mentioned that UT is something we all want others to write but they don't want to write, the relatively simple coding routines and patterns of the Go language allow everyone to pay attention to UT and be willing to write it. Lol.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.