Unit Testing 3.0 Practice Golang Quality Ecosystem Construction

R&D: Can’t we just write a single test?

5b3a940e3eb5f9511efadc29d8a32dd5.png

7c0ceafbc7f731b5dc1a1adb7a0774b6.png

  • End-to-end testing: As Martin Fowler said, a large number of end-to-end tests increase testing time and make testing expensive.

  • Unit testing: The execution is faster and the maintenance cost is lower. Therefore, the accumulation of unit testing is a must for us to move towards engineering excellence. The execution of unit testing also makes the testing granularity finer, making it easier to find defects in our code.

Each of the above points explains the necessity of unit testing. Among the top Internet companies, unit testing is considered necessary and profitable. Therefore, R&D students under the Excellence Project must write unit tests.

The overall idea and practice of Golang unit testing

Comparison of current implementation methods and optimization points in 2.0 unit test implementation


Unit testing 2.0

Unit testing 3.0

access cost

-Each application maintains its own unit test script, which is too customized, non-standard, and difficult to maintain.

-Integrate the unit test scripts of each application into the Aone Lab plug-in to provide universal execution scripts, which greatly reduces access costs and eliminates the need for users to maintain bloated single scripts.

Test resource issues

- Provide a fixed machine. If the test resources are not released in time during each execution, the machine performance will be low and the disk usage will be too high.

-Integrate unit tests into plug-in form, and use plug-and-play containerized resources to release test resources after each unit test is executed, reducing maintenance costs.

Differences in single tests performed by each application

-The execution environment version of Golang cannot be specified during execution;

-In the collection of coverage, it is impossible to specify which files to filter and not to count the coverage;

-Optimizing single test instructions requires modifying all application scripts, which makes each iteration very costly.

-Supports all Golang versions;

-Supports ignoring statistics in coverage calculation;

-Supports skipping the execution of some cases in unit test execution;

-In terms of executing unit tests, by optimizing gc, modifying cpu execution parameters, and optimizing the execution path of unit tests, the execution speed of single tests has been greatly improved;

-Support unit testing to detect data race issues.

Coverage collection is inaccurate

-In coverage collection, use the two components go-cov and diff-cover to generate incremental coverage and line coverage. All files under the package that have not written single tests will be missing, and unexecuted business code will not be executed. Statistics result in the overall coverage calculation being inaccurate.

In -3.0, by rewriting the implementation of incremental coverage, the incremental code coverage is recalculated based on the results of git diff and the coverage file to produce accurate incremental coverage;

-Line coverage uses Go's native ast parsing to generate function code lines for all files, solving the problem of inaccurate line coverage statistics.

Report display

-For single test execution, the test report content and coverage display are relatively simple, and users cannot clearly see test problems.

-In the implementation of 3.0, the overall test report was converted into HTML and the page was beautified to make the report display clearer;

-And access accurate coverage data to customize a set of report display methods, making the generated reports more beautiful and clear.

Let’s start with the Golang single test plug-in:

The overall architecture of the plug-in:

6c2926f44f189a67c6e2ba2db1735c40.png

In the entire CI process, we rely on the Action workflow provided by Aone Labs to implement the Golang unit testing plug-in. In the plug-in, we perform Go single testing, full coverage scanning, and incremental coverage scanning respectively. , scanning of branch coverage.

Based on the compilation characteristics of the Go language, we compile the Go service into individual binary files, execute each task in the Bash environment, and obtain the final result.

The code structure of the plug-in is as follows:

aone-golang-ut-plugin


    |--main    // 主入口文件


    |--bootstrap.sh  // 插件执行依赖环境安装 go&python3


    |--execute.sh   // 主执行文件


    |--log.sh      // 日志文件


    |--config.yml  //插件接入核心.yml文件


    |--util.sh   // shell工具类


    |--init.sh  // 初始化项目


    |--bin      //插件执行依赖bin文件


        |-go-coverage-engine   // 覆盖率计算引擎 


        |-go-ci-tools    // Go持续集成通用工具


        |-upload   // 测试报告上传组件

Plug-in execution timing diagram:

313ebdfd11f8a9e38fbeb70c9f1cc1ba.png

Execution of Go unit tests

Currently, Go's unit testing is executed directly using Go's official unit test Cli command. Please refer to Go's official information.

Single test command example:

go test ./... -timeout 3m -v -gcflags=-l \
       -cover=true -coverprofile=$coverFile -coverpkg=./... -mod=vendor

We execute this unit test command in the root directory of the Go project to run the unit test of the Go project and generate the coverage file. According to the Flag tag given in the unit test command, such as Cover, Coverprofile, etc., the unit test can be generated. Test coverage information.

During use, we can directly use the plug-in to customize the single test command of the current project in the plug-in, for example:

d39c7432ee161943850b9851b67904fc.png

This makes it easy to run single tests during continuous integration.

Practical results and access

Laboratory execution results:

b8fd6840fdc29918ddc12e3448873281.png

View test report:

Report of unit test execution results: It contains the execution results of single test functions, details of single test execution, and details of branch coverage.

e882baef81b8aca3a75e84e6c80168a0.png

Report of row incremental coverage:

7b124a0011e79840ee7c9eaa227315cc.png

Currently, 50+ applications have been connected to it 

How to access and use?

The simplest access method realizes the most powerful functions.

Select the Amap Golang single test plug-in in the laboratory and fill in the single test command of the current project.

Reference links:

[1]https://pkg.go.dev/cmd/go#hdr-Testing_flags

Recommended reading

Follow "Amap Technology" to learn more

Guess you like

Origin blog.csdn.net/amap_tech/article/details/131238265