C++ 如何编写好的单元测试?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1540960/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:20:33  来源:igfitidea点击:

How to write good Unit Tests?

c++unit-testingtdd

提问by Aaron Berry

Could anyone suggest books or materials to learn unit test?

任何人都可以推荐书籍或材料来学习单元测试吗?

Some people consider codes without unit tests as legacy codes. Nowadays, Test Driven Development is the approach for managing big software projects with ease. I like C++ a lot, I learnt it on my own without any formal education. I never looked into Unit Test before, so feel left out. I think Unit Tests are important and would be helpful in the long run. I would appreciate any help on this topic.

有些人认为没有单元测试的代码是遗留代码。如今,测试驱动开发是一种轻松管理大型软件项目的方法。我非常喜欢 C++,我在没有任何正规教育的情况下自学了它。我以前从未研究过单元测试,所以感觉被冷落了。我认为单元测试很重要,从长远来看会有帮助。我将不胜感激有关此主题的任何帮助。

My main points of concern are:

我的主要关注点是:

  1. What is a Unit Test? Is it a comprehensive list of test cases which should be analyzed? So lets us a say i have a class called "Complex Numbers" with some methods in it (lets says finding conjugate, an overloaded assignment operator and an overloaded multiplication operator. What should be typical test cases for such a class? Is there any methodology for selecting test cases?

  2. Are there any frameworks which can create unit tests for me or i have to write my own class for tests? I see an option of "Test" in Visual Studio 2008, but never got it working.

  3. What is the criteria for Units tests? Should there be a unit test for each and every function in a class? Does it make sense to have Unit Tests for each and every class?

  1. 什么是单元测试?它是应该分析的测试用例的完整列表吗?因此,让我们说我有一个名为“复数”的类,其中包含一些方法(可以说找到共轭、重载赋值运算符和重载乘法运算符。此类类的典型测试用例应该是什么?是否有任何方法?用于选择测试用例?

  2. 是否有任何框架可以为我创建单元测试,或者我必须编写自己的测试类?我在 Visual Studio 2008 中看到了“测试”选项,但从未让它工作。

  3. 单元测试的标准是什么?是否应该对类中的每个函数进行单元测试?对每个班级都进行单元测试有意义吗?

采纳答案by Ash

An important point (that I didn't realise in the beginning) is that Unit Testing is a testing technique that can be used by itself, without the need to apply the full Test Driven methodology.

重要的一点(我一开始没有意识到)是单元测试是一种可以单独使用的测试技术,无需应用完整的测试驱动方法。

For example, you have a legacy application that you want to improve by adding unit tests to problem areas, or you want to find bugs in an existing app. Now you write a unit test to expose the problem code and then fix it. These are semi test-driven, but can completely fit in with your current (non-TDD) development process.

例如,您希望通过向问题区域添加单元测试来改进遗留应用程序,或者您希望在现有应用程序中查找错误。现在您编写一个单元测试来暴露问题代码,然后修复它。这些是半测试驱动的,但可以完全适应您当前的(非 TDD)开发过程。

Two books I've found useful are:

我发现有用的两本书是:

Test Driven Development in Microsoft .NET

Microsoft .NET 中的测试驱动开发

A very hands on look at Test Driven development, following on from Kent Becks' original TDD book.

继 Kent Becks 的原始 TDD 书籍之后,对测试驱动开发的深入了解。

Pragmatic Unit Testing with C# and nUnit

使用 C# 和 nUnit 进行实用的单元测试

It comes straight to the point what unit testing is, and how to apply it.

它直截了当地说明了什么是单元测试,以及如何应用它。

In response to your points:

针对你的观点:

  1. A Unit test, in practical terms is a single method in a class that contains just enough code to test one aspect / behaviour of your application. Therefore you will often have many very simple unit tests, each testing a small part of your application code. In nUnit for example, you create a TestFixture class that contains any number of test methods. The key point is that the tests "test a unit" of your code, ie a smallest (sensible) unit as possible. You don't test the underlying API's you use, just the code you have written.

  2. There are frameworks that can take some of the grunt work out of creating test classes, however I don't recommmend them. To create useful unit tests that actually provide a safety net for refactoring, there is no alternative but for a developer to put thought into what and how to test their code. If you start becoming dependent on generating unit tests, it is all too easy to see them as just another task that has to be done. If you find yourself in this situation you're doing it completely wrong.

  3. There are no simple rules as to how many unit tests per class, per method etc. You need to look at your application code and make an educated assessment of where the complexity exists and write more tests for these areas. Most people start by testing public methods only because these in turn usually exercise the remainder of the private methods. However this is not always the case and sometimes it is necessary to test private methods.

  1. 单元测试,实际上是一个类中的一个方法,它只包含足够的代码来测试应用程序的一个方面/行为。因此,您通常会有许多非常简单的单元测试,每个单元测试都测试应用程序代码的一小部分。例如,在 nUnit 中,您创建一个包含任意数量的测试方法的 TestFixture 类。关键是测试“测试一个单元”你的代码,即尽可能最小(合理)的单元。您不测试您使用的底层 API,只测试您编写的代码。

  2. 有一些框架可以消除创建测试类的一些繁重工作,但是我不推荐它们。要创建有用的单元测试,实际上为重构提供安全网,除了开发人员考虑测试代码的内容和方式之外别无他法。如果您开始依赖生成单元测试,很容易将它们视为另一项必须完成的任务。如果你发现自己处于这种情况,那你就完全错了。

  3. 对于每个类、每个方法等有多少单元测试没有简单的规则。您需要查看您的应用程序代码,并对存在的复杂性进行有根据的评估,并为这些区域编写更多测试。大多数人从测试公共方法开始只是因为这些通常会依次执行其余的私有方法。然而,情况并非总是如此,有时需要测试私有方法。

In short, even experienced unit testers start by writing obvious unit tests, then look for more subtle tests that become clearer once they have written the obvious tests. They don't expect to get every test up-front, but instead add them as they come to their mind.

简而言之,即使是有经验的单元测试人员也会从编写明显的单元测试开始,然后寻找更微妙的测试,一旦他们编写了明显的测试,这些测试就会变得更加清晰。他们不希望预先获得每个测试,而是在他们想到时添加它们。

回答by Kenneth Cochran

While you've already accepted an answer to your question I'd like to recommend a few other books not yet mentioned:

虽然您已经接受了问题的答案,但我想推荐一些尚未提及的其他书籍:

  • Working Effectively with Legacy Code - Michael Feathers - As far as I know this is the only book to adequately tackle the topic of turning existing code that wasn't designed for testability into testable code. Written as more of a reference manual, its broken down into three sections: An overview of the tools and techniques, A series of topical guides to common road blocks in legacy code, A set of specific dependency breaking techniques referenced throughout the rest of the book.
  • Agile Principles, Patterns, and Practices - Robert C. Martin - Examples in java, there is a sequel with examples in C#. Both are easy to adapt to C++
  • Clean Code:A Handbook of Agile Software Craftsmanship - Robert C. Martin - Martin describes this as a prequel to his APPP books and I would agree. This book makes a case for professionalism and self-discipline, two essential qualities in any serious software developer.
  • 有效处理遗留代码 - Michael Feathers - 据我所知,这是唯一一本充分解决将现有代码不是为可测试性而设计的可测试代码的主题的书。更像是一本参考手册,分为三个部分:工具和技术概述、遗留代码中常见障碍的一系列主题指南、本书其余部分引用的一组特定的依赖破坏技术.
  • 敏捷原则、模式和实践 - Robert C. Martin - Java 示例,还有 C# 示例的续集。两者都很容易适应C++
  • Clean Code:A Handbook of Agile Software Craftsmanship - Robert C. Martin - Martin 将其描述为他的 APPP 书籍的前传,我同意。本书为专业精神和自律提供了案例,这是任何认真的软件开发人员的两个基本素质。

The two books by Robert (Uncle Bob) Martin cover much more material than just Unit testing but they drive home just how beneficial unit testing can be to code quality and productivity. I find myself referring to these three books on a regular basis.

罗伯特(鲍勃叔叔)马丁的两本书涵盖的内容远不止单元测试,但它们让我们明白单元测试对代码质量和生产力的益处。我发现自己经常参考这三本书。

回答by utnapistim

Nowadays, Test Driven Development is the approach for managing big software projects with ease.

如今,测试驱动开发是一种轻松管理大型软件项目的方法。

That is because TDD allows you to make sure after each change that everything that worked before the change still works, and if it doesn't it allows you to pinpoint what was broken, much easier. (see at the end)

这是因为 TDD 允许您在每次更改后确保在更改之前工作的所有内容仍然有效,如果没有,它允许您查明损坏的地方,容易得多。(见文末)

What is a Unit Test? Is it a comprehensive list of test cases which should be analyzed?

什么是单元测试?它是应该分析的测试用例的完整列表吗?

A Unit Test is a piece of code that asks a "unit" of your code to perform an operation, then verifies that the operation was indeed performed and the result is as expected. If the result is not correct, it raises / logs an error.

单元测试是一段代码,它要求您的代码的“单元”执行操作,然后验证操作是否确实已执行并且结果是否符合预期。如果结果不正确,则会引发/记录错误。

So lets us a say i have a class called "Complex Numbers" with some methods in it (lets says finding conjugate, an overloaded assignment operator and an overloaded multiplication operator. What should be typical test cases for such a class? Is there any methodology for selecting test cases?

因此,让我们说我有一个名为“复数”的类,其中包含一些方法(可以说找到共轭、重载赋值运算符和重载乘法运算符。此类类的典型测试用例应该是什么?是否有任何方法?用于选择测试用例?

Ideally, you would test all the code.

理想情况下,您将测试所有代码。

  • when you create an instance of the class, it is created with the correct default values

  • when you ask it to find the conjugates, it does finds the correct ones (also test border cases, like the conjugate for zero)

  • when you assign a value the value is assigned and displayed correctly

  • when you multiply a complex by a value, it is multiplied correctly

  • 当您创建类的实例时,会使用正确的默认值创建它

  • 当你要求它找到共轭时,它确实找到了正确的(也测试边界情况,比如零的共轭)

  • 当您分配一个值时,该值被正确分配和显示

  • 当你将一个复数乘以一个值时,它被正确地相乘

Are their any frameworks which can create unit tests for me or i have to write my own class for tests?

他们是否有任何框架可以为我创建单元测试,或者我必须编写自己的测试类?

See CppUnit

CppUnit

I see an option of "Test" in Visual Studio 2008, but never got it working.

我在 Visual Studio 2008 中看到了“测试”选项,但从未让它工作。

Not sure on that. I haven't used VS 2008 but it may be available just for .NET.

不确定。我没有使用过 VS 2008,但它可能只适用于 .NET。

What is the criteria for Units tests? Should there be a unit test for each and every function in a class? Does it make sense to have Unit Tests for each and every class?

单元测试的标准是什么?是否应该对类中的每个函数进行单元测试?对每个班级都进行单元测试有意义吗?

Yes, it does. While that is an awful lot of code to write (and maintain with every change) the price is worth paying for large projects: It guarantees that your changes to the code base do what you want them to and nothing else.

是的,它确实。虽然要编写大量代码(并在每次更改时进行维护),但为大型项目付出的代价是值得的:它保证您对代码库的更改按照您的要求执行,没有其他任何事情

Also, when you make a change, you need to update the unit-tests for that change (so that they pass again).

此外,当您进行更改时,您需要更新该更改的单元测试(以便它们再次通过)。

In TDD, you first decide what you want the code to do (say, your complex numbers class), then write the tests that verify those operations, then write the class so that the tests compile and execute correctly (and nothing more).

在 TDD 中,您首先决定您希望代码做什么(例如,您的复数类),然后编写验证这些操作的测试,然后编写类以便正确编译和执行测试(仅此而已)。

This ensures that you write the minimal code possible (and don't over-complicate the design of the complex class) and it also ensures that your code does what it does. At the end of writing the code, you have a way to test it's functionality and ensuring it's correctness.

这可以确保您编写尽可能少的代码(并且不会使复杂类的设计过于复杂),并且还可以确保您的代码完成它所做的工作。在编写代码的最后,您有一种方法来测试它的功能并确保它的正确性。

You also have an example of using the code that you will be able to access at any point.

您还有一个使用代码的示例,您可以随时访问该代码。

For further reading/documentation, look into "dependency injection" and method stubs as used in unit testing and TDD.

如需进一步阅读/文档,请查看单元测试和 TDD 中使用的“依赖注入”和方法存根。

回答by Jerry Coffin

  1. With test driven design, you normally want to write the tests first. They should cover the operations you're actually using/going to use. I.e. unless they're necessary for the client code to do its job, they shouldn't exist. Selecting test cases is something of an art. There are obvious things like testing boundary conditions, but in the end, nobody's found a really reliable, systematic way of assuring that tests (unit or otherwise) cover all the conditions that matter.

  2. Yes, there are frameworks. A couple of the best known are:
    Boost Unit Test Framework
    CPPUNit

    CPPUnit is a port of JUnit, so those who've used JUnit previously will probably find it comfortable. Otherwise, I'd tend to recommend Boost -- they also have a Test Libraryto help write the individual tests -- rather a handy addition.

  3. Unit tests should be sufficient to ensure that the code works. If (for example) you have a private function that's used internally, you generally don't need to test it directly. Instead, you test whatever provides the public interface. As long as that works correctly, it's no business of the outside world how it does its job. Of course, in some cases it's easierto test little pieces, and when it is, that's perfectly legitimate -- but ultimately you care about the visible interface, not the internals. Certainly the whole external interface should be exercised, and test cases generally chosen to exercise the paths through the code. Again, there's nothing massively different about unit tests versus other kinds. It's mostly just a more systematic way of applying normal testing techniques.

  1. 对于测试驱动设计,您通常希望先编写测试。它们应该涵盖您实际使用/将要使用的操作。即,除非它们是客户端代码完成其工作所必需的,否则它们不应该存在。选择测试用例是一门艺术。有一些明显的事情,比如测试边界条件,但最终,没有人找到一种真正可靠、系统的方法来确保测试(单元或其他)涵盖所有重要的条件。

  2. 是的,有框架。最著名的几个是:
    Boost 单元测试框架
    CPPUUnit

    CPPUnit 是 JUnit 的一个端口,所以那些以前使用过 JUnit 的人可能会觉得它很舒服。否则,我倾向于推荐 Boost——他们还有一个测试库来帮助编写单独的测试——而不是一个方便的补充。

  3. 单元测试应该足以确保代码工作。如果(例如)您有一个在内部使用的私有函数,您通常不需要直接测试它。相反,您测试提供公共接口的任何内容。只要它工作正常,它如何工作就与外界无关。当然,在某些情况下,测试小部分更容易,如果是,那是完全合法的——但最终你关心的是可见的界面,而不是内部结构。当然应该执行整个外部接口,并且通常选择测试用例来执行通过代码的路径。同样,单元测试与其他类型没有太大不同。它主要是应用正常测试技术的一种更系统的方式。

回答by Mathias

In .NET I strongly recommend "The Art of Unit Testing" by Roy Osherove, it is very comprehensive and full of good advice.

在 .NET 中,我强烈推荐 Roy Osherove 的“单元测试的艺术”,它非常全面且充满了很好的建议。

回答by Mark Brittingham

Unit tests are simply a way to exercise a given body of code to ensure that a defined set of conditions leads to the expected set of out comes. As Steven points out, these "exercises" should check across a range of criteria ("BICEP"). Yes, ideally you should test all of your classes and all of the methods in these classes although there is always some room for judgement: testing shouldn't be an end in itself but rather should support the wider project goals.

单元测试只是一种锻炼给定代码体的方法,以确保一组定义的条件导致预期的结果集。正如史蒂文指出的那样,这些“练习”应该检查一系列标准(“BICEP”)。是的,理想情况下,您应该测试所有类和这些类中的所有方法,尽管总有一些判断空间:测试本身不应是目的,而应支持更广泛的项目目标。

Ok, so...theory is nice but to really understand Unit Testing, my recommendation would be to pull together the appropriate tools and just get started. Like most things in programming, if you have the right tools, it is easy to learn by doing.

好的,所以......理论很好,但要真正理解单元测试,我的建议是将适当的工具放在一起,然后开始。与编程中的大多数事情一样,如果您拥有合适的工具,则很容易边做边学。

First, pick up a copy of NUnit. It is free, easy to install and easy to work with. If you'd like some documentation, check out Pragmatic Unit Testing in C# with NUnit.

首先,拿起一份NUnit。它是免费的,易于安装且易于使用。如果您需要一些文档,请查看使用 NUnit 在 C# 中进行的实用单元测试。

Next, go to http://www.testdriven.net/and get a copy of TestDriven.net. It installs into Visual Studio 2008 and gives you right-click access to a full range of testing tools including the ability to run NUnit tests against a file, directory or project (typically, tests are written in a separate project). You can also run tests with debugging or, coolest of all, run all the tests against a copy of NCover. NCover will show you exactlywhat code is being exercised so you can figure out where you need to improve your test coverage. TestDriven.net costs $170 for a professional license but, if you are like me, it will very quickly become an integral tool in your toolbox. Anyway, I've found it to be an excellent professional investment.

接下来,访问http://www.testdriven.net/并获取 TestDriven.net 的副本。它安装到 Visual Studio 2008 中,使您可以通过右键单击访问各种测试工具,包括针对文件、目录或项目运行 NUnit 测试的能力(通常,测试是在单独的项目中编写的)。您还可以通过调试运行测试,或者最酷的是,针对 NCover 的副本运行所有测试。NCover 将准确地向您显示正在执行的代码,以便您可以找出需要提高测试覆盖率的地方。TestDriven.net 的专业许可证费用为 170 美元,但如果您像我一样,它将很快成为您工具箱中不可或缺的工具。无论如何,我发现这是一项出色的专业投资。

Good luck!

祝你好运!

回答by monksy

I can't answer your question for Visual Studio 2008, but I know that Netbeanshas a few integrated tools for you to use.

我无法回答您关于 Visual Studio 2008 的问题,但我知道Netbeans有一些集成工具供您使用。

  1. The code coverage two allows for you to see which paths have been checked, and how much of the code is actually covered by the unit tests.
  2. It has the support for the unit tests built in.
  1. 代码覆盖率二允许您查看哪些路径已被检查,以及单元测试实际覆盖了多少代码。
  2. 它支持内置的单元测试。

As far as quality of tests I'm borrowing a bit from the "Pragmatic Unit Testing in Java with JUnit" by Andrew Hunt and David Thomas:

至于测试的质量,我从Andrew Hunt 和 David Thomas 的“使用 JUnit 的 Java 实用单元测试”中借用了一点:

Unit testing should check for BICEP: Boundary, Inverse relationships, Cross-checking, Error conditions, and Performance.

单元测试应该检查BICEPoundary,nverse关系,Ç罗斯检查,ēRROR条件,以及Performance。

Also quality of the tests are determined by A-TRIP: Automatic, Thorough, Repeatable, Independent, and Professional.

还测试的质量由下式确定的A-TRIPutomatic,Ťhorough,- [Repeatable,ndependent,和Professional。

回答by Michael Lloyd Lee mlk

Nowadays, Test Driven Development is the approach for managing big software projects with ease.

如今,测试驱动开发是一种轻松管理大型软件项目的方法。

TDD built on unit tests but they are different. You don't need to be use TDD to make use of unit tests. My personal preference is to write test first, but I don't feel I do the whole TDD thing.

TDD 建立在单元测试之上,但它们是不同的。您不需要使用 TDD 来使用单元测试。我个人的偏好是先写测试,但我不觉得我做了整个 TDD 事情。

What is a Unit Test?

什么是单元测试?

A Unit Test is a bit of code that tests the behaviour of one unit. How one unit is defined differs between people. But in general they are:

单元测试是测试一个单元行为的一小段代码。一个单位的定义因人而异。但总的来说,它们是:

  1. Quick to run
  2. Independent from each other
  3. Test only a small part (a unit ;) of your code base.
  4. Binary outcome - That is it passes or fails.
  5. Should only test one outcome of the unit (for each outcome create a different unit test)
  6. Repeatable
  1. 快速运行
  2. 彼此独立
  3. 只测试代码库的一小部分(一个单元;)。
  4. 二元结果 - 即通过或失败。
  5. 应该只测试单元的一个结果(为每个结果创建一个不同的单元测试)
  6. 可重复

Are their any frameworks which can create unit tests

他们是否有任何可以创建单元测试的框架

To write the tests - Yes but I've never seen anyone say anything nice about them.
To help you write & run tests, a whole bunchof them.

编写测试 - 是的,但我从未见过有人对他们说任何好话。
为了帮助您编写和运行测试,一大堆

Should there be a unit test for each and every function in a class?

是否应该对类中的每个函数进行单元测试?

You have a few different camps in this - the 100%ers would say yes. Every method must be tested and you should have 100% code coverage. The other extreme is that unit tests should only cover areas that you have even encounter bugs or you expect to find bugs. The middle ground (and the stand I take) is to unit tests everything that is not "too simple to break". Setters/getters and anything that just calls a single other method. I aim to have 80% code coverage and a low CRAPfactor (so a low chance I've been naughty and decided to not test something as it was "too complex to test).

你有几个不同的阵营 - 100%的人会说是。每个方法都必须经过测试,并且您应该拥有 100% 的代码覆盖率。另一个极端是单元测试应该只覆盖您甚至遇到错误或您希望找到错误的区域。中间立场(以及我采取的立场)是对不是“太简单而无法破坏”的所有内容进行单元测试。Setter/getter 和任何只调用一个其他方法的东西。我的目标是拥有 80% 的代码覆盖率和较低的CRAP系数(因此我很调皮并决定不测试某些东西,因为它“太复杂而无法测试)。

The book that helped me "get" unit tests JUnit in Action. Sorry I don't do much in the C++ world, so I can not suggest a C++ based alternative.

帮助我“获得”单元测试JUnit in Action 的书。抱歉,我在 C++ 世界中做的不多,所以我不能建议基于 C++ 的替代方案。

回答by Frank Schwieterman

Buy the book "xUnit Test Patterns: Refactoring Test Code". Its very excellent. It does cover high-level strategy decisions as well as low level test patterns.

购买“xUnit 测试模式:重构测试代码”一书。它非常出色。它确实涵盖了高级策略决策以及低级测试模式。

回答by ChrisW

Here's something on when not to write unit tests (i.e. on when it's viable and even preferable to skip unit testing): Should one test internal implementation, or only test public behaviour?

这里有一些关于什么时候不编写单元测试(即什么时候可以跳过单元测试甚至更可取):应该测试内部实现,还是只测试公共行为?

The short answer is:

简短的回答是:

  • When you can automate integration tests (because it's important to have automated tests, but those tests don't have to be unit tests)
  • When it's cheap to run the integration test suite (no good if it takes two days to run, or if you can't afford to let every developer have access to an integration test equipment)
  • When it isn't necessary to find bugs before integration testing (which depends in part on whether components are developed separately or incrementally)
  • 何时可以自动化集成测试(因为自动化测试很重要,但这些测试不一定是单元测试)
  • 当运行集成测试套件很便宜时(如果运行需要两天时间,或者如果你不能让每个开发人员都使用集成测试设备,那就不好了)
  • 当在集成测试之前没有必要发现错误时(这部分取决于组件是单独开发还是增量开发)