Talking about c++ unit testing

overview


What is unit testing?

Unit testing refers to the work of checking and verifying the smallest testable unit in the software in isolation from other parts of the program, where the smallest testable unit usually refers to a function, interface or class.

Unit testing runs through the entire process of development and is carried out along with the generation of new functional modules. Unit testing does not take more time. On the contrary, unit testing plays a big role in improving code efficiency, reducing the number of bugs, and orderly developing development work.

Scenario example


A developer uses step-by-step debugging to track down and find a bug because the top-level code runs without any output. When he corrects this bug, he finds several other bugs at the same time. After doing this several times, the bug still exists. On the program output side, there is still no result. So, the developer is completely confused as to why this is happening, and thinks there is no reason for this behavior with no output.

If unit tests are introduced for the above scenario, the situation will be as follows:

During the development process, every time a function is written, a simple test is added to determine whether the function is consistent with the expected function. Developers don't continue to write new code until they confirm the function they just wrote. That is to say, every time a function is written, the development of new functions must be introduced after verifying that its functions are available. The final result is that because there are unit tests to ensure that the functions of each new function are available, the final top-level program also has output, and the completely nonsensical situation in the previous first scenario does not appear.

Error correction


Writing unit tests is too time consuming. Much less time is spent on unit testing than on testing at the end of the project. Of course, the premise is that the developer must have a good understanding of what kind of function the unit to be tested needs to achieve and what the expected output is.

Testing code is not the job of development. If a developer throws a random piece of unsure code to the test team, then in fact the developer has not done his job. In fact, expecting someone else to clean up your code is bad practice.

These codes can be compiled through. There is a very common misconception that a successful compilation is a sign of success; in fact, any compiler and interpreter can only verify the correctness of syntax, not the correctness of behavior.

For some important module components or functional interfaces, it is necessary to write unit tests. Be able to do some more complete verification of the interface parameters and expected results, and find some potential dangers. And with the help of some unit testing frameworks, the interface can be stress tested to verify the operation in extreme cases.

Benefits of unit testing?

Unit testing helps:

1. Modularize your code, since the testability of your code depends on its design, unit testing helps to break it down into dedicated parts that are easy to test.

2. To avoid regression, if you have a suite of unit tests, you can run it iteratively to make sure everything works correctly every time you add a new feature or make a change.

3. Documenting your code, running, debugging or even just reading tests can provide a lot of information about how the original code works, so you can use them as implicit documentation.

How to carry out unit testing


How to carry out unit testing in actual software projects?

Not all codes need to be unit tested, and usually only important modules or core modules are tested with unit tests.

Good practices for unit testing include:

Create tests for exposed functionality, including class constructors and operators.

Cover all code paths and check for trivial cases and edge cases, including those where the input data is incorrect (see Negative Testing ).

Make sure that each test runs independently and does not block the execution of other tests.

Organize tests in a way that does not affect the order in which test results are run.

Ideally, unit test execution, code coverage statistics and continuous integration pipelines need to be integrated to ensure that unit tests are automatically triggered every time code is submitted. And the code coverage rate is automatically counted during the execution of the unit test, and finally the "unit test pass rate" and "code coverage rate" are used as the criteria to determine whether the code submission can be accepted.

How to write effective unit tests


Components of unit testing

A general unit test consists of the following parts:

1. Test data: As stable as possible, reduce dependence on uncertain factors.

2. Logical execution body: It is necessary to clarify which function and which branch logic the current test case is testing, and do not cover most of them at once.

3. Result verification: As complete as possible, don't just verify the return value of the function.

Principles of unit testing

The principles that unit testing must follow:

1. Independence: Unit tests are self-contained, can be run independently, and do not depend on any external factors such as file system or database.

2. Idempotency: Each unit test run should be consistent with its results, and the test should not rely on uncertain factors such as time and date.

3. Fast: Do not rely on time-consuming operations such as network requests.

Experience summary

When writing unit tests, it is recommended to think from the following perspectives:

What functions are implemented, what data is processed, and what is the final output?

Where are the exceptions and boundaries?

Are the key results of the function verified? Contains return and intermediate values.

Where is the risk of the function, which part of the logic is not confident, and is most likely to make mistakes?

Not all functions require a single test, such as get/set with relatively simple logic, do not necessarily need to be written.

Environment build


Introduction to common unit testing tools for C++

There are many C++ testing frameworks like Catch, Boost.Test, UnitTest++, lest, bandit, igloo, xUnit++, CppTest, CppUnit, CxxTest, cpputest, googletest, QtTest, cute, doctest and others.

Introduction to Gtest

Google C++ unit testing framework (Gtest for short), which can be used on multiple platforms (including Linux, Mac OS X, Windows, Cygwin and Symbian), provides rich assertions, fatal and non-fatal failure judgments, and can perform value parameter testing, type parameterization testing.

Gtest use, see blog:

Introduction to Doctest

gtest needs to be installed and sometimes brings a lot of inconvenience. For example, downloading and installing gtest due to network reasons may fail due to network reasons. In addition to gtest, there are many lightweight and easy-to-use unit testing libraries, such as doctest and catch. Compared with gtest, which needs to be compiled/installed, they are all header only, and they can be used for unit testing when they are directly included in the project. Portable does not have any dependencies, and the requirements for the compiler version are not high.

doctest is a new C++ testing framework. Compile-time (by orders of magnitude) and runtime are the fastest compared to other feature-rich alternatives. Write tests directly in production code by providing a fast, transparent and flexible test runner with a clean interface.

The main difference between doctest and other testing frameworks is that it is lightweight and non-intrusive.

Finally, I would like to thank everyone who has read my article carefully. Reciprocity is always necessary. Although it is not a very valuable thing, you can take it away if you need it:

These materials should be the most comprehensive and complete preparation warehouse for [software testing] friends. This warehouse has also accompanied tens of thousands of test engineers through the most difficult journey, and I hope it can help you! Partners can click the small card below to receive

Guess you like

Origin blog.csdn.net/OKCRoss/article/details/131437483