是否有人用Visual-C ++做“真实的” TDD,如果可以,他们是如何做到的?[关闭]


10

测试驱动开发意味着在代码之前一定周期之后编写测试

  • 写测试
  • 检查测试(运行)
  • 编写生产代码
  • 检查测试(运行)
  • 清理生产代码
  • 检查测试(运行)

就我而言,这只有在您的开发解决方案允许您非常快速地在生产代码和测试代码之间切换以及对特定生产代码部分执行测试的情况下才有可能。

现在,尽管存在许多C ++单元测试框架(我正在使用Bost.Test atm。)看来,实际上并没有任何像样的(对于本机C ++而言)Visual Studio(插件)解决方案能够使TDD周期可承受,与使用的框架无关。

“可以承受”表示只需单击一下即可对某个cpp文件运行测试,而无需手动设置单独的测试项目等。“可以承受”还表示一个简单的测试开始(链接!)并且运行非常快。

那么,有哪些工具(插件)和技术可以使使用Visual Studio进行本机C ++开发的TDD周期成为可能?

注意:我可以使用免费或“商业”工具。

没有框架建议。(除非框架具有专用的Visual Studio插件,并且您要推荐该插件。)


编辑说明:到目前为止的答案提供了有关如何将单元测试框架集成到Visual Studio中的链接。这些资源或多或少描述了如何获取UT框架进行编译以及如何运行您的第一个测试。不是这个问题的意思。我认为要真正有效地工作,将单元测试放在手动维护(!)中,将vcproj与您的生产类分开会增加太多开销,以致TDD“不可能”。据我所知,您没有为Java或C#事物添加额外的“项目”以启用单元测试和TDD,这是有充分的理由的。这应该 只要有正确的工具,C ++就可以实现,但似乎(这个问题是关于)TDD / C ++ / VS的工具很少。


到处搜寻,我发现一个工具VisualAssert似乎朝着正确的方向发展。但是,afaiks,它似乎并未得到广泛使用(与CppUnit,Boost.Test等相比)。


编辑:我想在此问题的上下文中添加评论。我认为它很好地概括了问题的一部分:(Billy ONeal的评论)

Visual Studio不使用用户可以合理编辑的“构建脚本”。一个项目产生一个二进制文件。而且,Java具有Java从不构建完整二进制文件的特性-您构建的二进制文件只是类文件的ZIP。因此,可以分别手动编译然后JAR一起编译(使用例如7z)。C ++和C#都实际上链接了它们的二进制文件,因此,一般来讲,您不能编写这样的脚本。最接近的是分别编译所有内容,然后进行两个链接(一个用于生产,一个用于测试)。


2
As far as I am aware, you do not add extra "projects" to a Java or C# thing to enable Unit Tests and TDD,<-我认为这是不正确的。通常,您在C#中也有多个项目。您不想将测试代码发送到生产二进制文件中。
Billy ONeal

2
我从未见过该框架处理过该问题。生成二进制文件需要一个项目。您需要两个二进制文件;一种带有测试代码,另一种带有生产代码。因此,您需要两个项目。没有办法解决。
Billy ONeal

1
@BillyONeal,除了我的一个(Java)项目以外,所有项目都包含主要和测试源-然后,构建脚本选择要放入可部署工件中的部分。
罗伯特·马克·布拉姆

2
@Robert:Visual Studio不使用用户可以合理编辑的“构建脚本”。一个项目产生一个二进制文件。而且,Java具有Java从不构建完整二进制文件的特性-您构建的二进制文件只是类文件的ZIP。因此,可以手动将JAR分别编译出来(例如使用7z)。C ++和C#都实际上链接了它们的二进制文件,因此,一般来讲,您不能编写这样的脚本。最接近的是分别编译所有内容,然后进行两个链接(一个用于生产,一个用于测试)。
Billy ONeal

4
认真吗 “提示:每个测试应包含一个主要功能并生成一个可执行文件。” 对于任何合理数量的测试,这听起来都太慢了。即使它们意味着每个可执行文件只有一个测试夹具,它仍然是IMO愚蠢的建议。尝试通过成千上万的测试(对于中型项目)或成千上万的测试(对于大型项目)来进行操作,您肯定会发疯。
合法化

Answers:


4

我已经写了一个由5部分组成的博客系列,有关使用C ++和Visual Studio进行TDD:第1 部分第2 部分第3 部分第4 部分第5部分

我不知道为什么您说您不使用C#进行额外的项目来进行TDD,因为这是我一直使用NUnit所做的事情,而且这似乎也是其他人使用NUnit所做的事情的典型表现。原因很简单:始终将测试代码与生产代码分开。对于带有Visual Studio的C ++,这意味着需要单独的项目,就像对C#和NUnit一样。根据我对Java世界的了解,这在那里也很普遍。

显然,每个人对于进行TDD的“承受能力”有不同的想法。几年来,我一直在练习我在博客文章中概述的方法,我发现这是可以忍受的。C ++是一种编译语言,当被测系统高度耦合时,编译工作可能会很慢。如果不重构为更松散的耦合设计,就无法摆脱它。

我的“一键式操作”是“构建解决方案”。如果构建的内容太多,则您始终可以在工作时卸载不相关的项目,然后构建解决方案将仅构建需要更改的项目的最小子集。

诚然,C ++的编译时间性质确实使它在TDD过程的每个周期中花费的时间比使用NUnit和C#花费的时间长一点,但是我从经过良好测试的C ++代码中获得的信心是值得的。否则,我将在调试器上花费更多的时间。我会谨慎使用gmock,因为它会大大增加测试编译时间。到目前为止,我基本上都没有使用轻量级的“伪”对象,并且很少需要完整的模拟功能。C ++的模拟框架主要基于模板,这可以显着增加编译时间,因此应将它们保留给您真正需要模拟的地方,而伪造品则不会。

我曾经考虑过创建一个Boost.Test单元测试项目向导来自动化为生产代码创建测试项目的一些样板性质,但是在完成几次之后,手动操作确实并不难。

至于有许多(150?)项目的解决方案,也有解决方法。一个明显的例子是找到相关项目的组并将它们捆绑在一起,然后开始使用它们/将它们作为一个单元发布。如果您确实需要重建/修改所有150个项目以进行TDD周期内的细微更改,那么您的代码是如此紧密地耦合在一起,以至于单元测试不会产生太大的变化。

通过查看netbeans IDE链接,我发现可以解析测试输出并在窗口中显示带有绿色或红色符号的小测试行的东西真让人眼前一亮,我想我会想念来自NUnit的东西,但实际上并没有错过。我发现对于仅发生失败的构建更为有用,然后我可以在错误窗口中双击以将光标放置在失败的断言的位置。


“……不确定为什么您说不使用C#进行额外的项目……从我对Java世界的了解来看,这在那里也很普遍……”我可能误解了。(至少对于.NET,因为您需要.NET的可执行文件-对于Java,您只需要类文件,所以我不太清楚额外的项目在哪里。)
Martin Ba

我不确定Java如何与项目一起使用。我在那里的经验有限。据我所知,我理解项目是IDE的产物,而不是语言。(严格来说,对于C#来说也是如此,但是我不知道任何人仅将命令行编译器用于简短的博客文章或演示以外的任何事情。)但是,即使在Java中,您也绝对要将测试代码与生产代码,这是单独的项目为您执行的工作。我从不建议有条件地编译C ++以分离生产和测试代码。
合法化

1
“将测试代码与生产代码分开,这是单独的项目为您所做的工作” –啊!好吧,不是,恕我直言。对于C ++和.NET,单独的“项目”是必需的,因为两者都需要创建一个可执行文件以运行任何内容,并且都需要创建(一个)可执行文件,因此您需要一个(一个)项目。我可以将测试代码与生产代码分开(或不分开),但是我发现必须添加一个(冗余的)“项目”来生成令人讨厌的测试可执行文件。:-)
Martin Ba

1
您需要两个内置产品:生产代码(静态库,共享库,可执行文件等)和测试可执行文件。在Visual Studio中,每个生成的产品都对应一个项目,因此您需要两个项目。确实没有比这更复杂的了。单元测试项目不是多余的。
合法化

2

我没有使用Visual-C ++,但是我正在使用Ct执行TDD,并使用googletest和googlemock,并将QtCreator作为我的IDE。多年前,我使用Visual-C ++进行了类似的设置,但是使用了不同的单元测试框架。

我发现有用的是将项目分成几个子项目。

  1. 包含99%的实际项目源代码的静态或动态库。
  2. 一个主要由运行常规程序的main()方法组成的项目。
  3. 一个测试项目,包含一个main()来运行我的测试框架以及许多包含测试和模拟对象的文件。

通过此设置,我的IDE负责将文件添加到各个项目中,如果可以正确确定依赖项,则可以部分重建来运行所有单元测试。我什至目前已将其设置为在构建后立即运行所有测试。我正在使用的CI Jenkins也可以运行并提供测试结果和覆盖率数据。

如果您碰巧在测试夹具TestFoo下命名了Foo的所有单元测试,则可能在IDE中为该文件添加一个自定义启动器,以运行文件Foo.cpp的单元测试。我不确定如何针对Visual-C ++进行精确设置,但我确实认为有可能。


有用的信息,尽管我甚至称其为“通用建议” :-) ...对于我们的旧版产品而言,这也不是切实可行的,但是向旧版产品中添加测试无论如何还是很痛苦的(并且我希望至少使添加测试装备变得容易)。
马丁·巴

2

我使用MSTest来测试本地C ++代码。
这是关于这种方式的精彩博客文章: http //blogs.msdn.com/b/jsocha/archive/2010/11/19/writing-unit-tests-in-visual-studio-for-native-c。 aspx

是的,至少会有两个项目-一个用于应用程序本身,一个用于测试。
我没有使用静态库制作第三个项目,而是将应用程序的源代码添加到测试项目中,因此解决方案如下所示:

[-] Solution 'Foo'      Foo\Foo.sln
 |-[-] Foo              Foo\Foo\Foo.vcproj
 |  |-[-] include
 |  |  |- foo.h         Foo\Foo\foo.h
 |  |  |- bar.h         Foo\Foo\bar.h
 |  |
 |  |-[-] source
 |     |- foo.cpp       Foo\Foo\foo.cpp
 |
 |-[-] Foo.Tests        Foo\Foo.Tests\Foo.Tests.vcproj
    |                        (Additional include directory: "..\Foo")
    |-[-] include
    |  |- FakeBar.h     Foo\Foo.Tests\FakeBar.h
    |
    |-[-] source
       |-[-] app
       |  |- foo.cpp    Foo\Foo\foo.cpp    -- not in Foo.Tests\
       |
       |-[-] unit-tests
          |- foo_Tests.cpp   Foo\Foo.Tests\foo_Tests.cpp
          |- bar_Tests.cpp   Foo\Foo.Tests\bar_Tests.cpp

我发现在测试纯本机C ++代码时,使用C ++ / CLI进行单元测试只会使工作变得混乱。但是,我已经使用NUnit测试C ++ / CLI应用程序代码。我用C#编写了测试,效果很好。(现有的代码库是C ++ / CLI,我不想将其移植到C#。)
合法化

此外,如果您的测试是在C ++ / CLI中进行的,那么您将无法在其他平台上运行它们。我使用C ++的大多数地方都需要跨平台的编译能力。当然,您不能在其他平台上重用VS项目,但是拥有Makefiles或SConscripts并不是什么大问题。
合法化

@legalize我们也不能在非Windows平台上重用WinAPI(以及COM和其他Windows特定技术)。
Abyx 2011年

是的,您当然不能在非Windows平台上使用Windows特定技术。我的观察只是,如果您有平台无关的代码,那么您就不想将单元测试绑定到特定的平台。在以前的雇主那里,我们评估了大量的单元测试框架和方法。我们选择Boost.Test是因为它是跨平台的,如果有关单元测试的任何事情最终落入C ++标准库中,则很有可能是Boost.Test。
合法化

2

也许是一天的晚上,但是如果我正确地阅读了您的问题,您正在寻找改善TDD周期的技术吗?这里没有提到它,但是您是否看过VS中的构建后事件?

我们的解决方案通常是有组织的(显示项目依赖项)...

MAIN-APP > LIB1, LIB2, UNIT-TEST-APP
UNIT-TEST-LIB1 > LIB1
UNIT-TEST-LIB2 > LIB2
UNIT-TEST-APP > UNIT-TEST-LIB1, UNIT-TEST-LIB2

MAIN-APP的构建后事件将运行UNIT-TEST-APP

UNIT-TEST-APP的构建后事件将自行运行(只需将“ $(TargetPath)”作为要在构建后事件中运行的命令)。

(这确实意味着在构建MAIN-APP时,单元测试可以运行两次,但这对我们而言并不是真正的问题!)

如上所述,是的,有一点的设置此结构的努力,但一旦它的存在,增加测试很简单。

因此,您要做的就是构建主应用程序,单元测试将自动运行!


1

好吧,不知道这是否有帮助,但是Brett L. Schuchert提供了一些有关TDD的精彩视频。不幸的是,他没有显示“ C ++”和“ VS”的组合,但是

使用C#和VS的TDD:http//vimeo.com/album/210446

使用C ++和Eclipse的TDD:http//vimeo.com/13240481

也许您可以从这两个中解决。

编辑:C ++视频当然是关于在Eclipse中使用CppUTest测试框架。当我发布它时,我认为它应该很容易在VS中使用。所以我用谷歌搜索了一下:

http://schuchert.wikispaces.com/tdd.cpp.NotesOnCppUTest

它为您提供了有关如何在Visual Studio中使用CppUTest的信息。


2
博士-我(仅)看了TDD / Eclipse视频,但我要否决这个视频。该视频恰好显示了我感兴趣的内容,即如何编写单元测试代码。问题(不是这个问题)不是在编写单元测试,而是如何它们与您的C ++生产开发正确集成,我看不到这些视频如何为您提供帮助。
马丁·巴

虽然在这个问题的背景下我对这个答案不满意,但我想补充一点,这些视频非常不错。我发现Eclipse / TDD / C ++很有趣。这只是无济于事:-)
马丁·巴

@马丁:看我的编辑。
Doc Brown

感谢您的努力,尽管我认为此附加链接对解决此问题确实没有帮助,但我认为我需要自己进行一些编辑。
马丁·巴

@马丁:好吧,我再读一次你的问题和你对“可承受的”的定义,但是你不期望太多吗?设置单元测试项目不是“一键式”解决方案,但是编写实际单元测试的工作量要比数量级高,无论使用哪种框架。
Doc Brown

1

谷歌测试
如何与vc ++集成

您不需要插件,测试只是另一个目标。没有插件可以使用c ++生成测试,如果需要的话,可以使用evne来测试诸如赋值之类的毫无意义的东西


“即使您可以测试诸如任务之类的毫无意义的东西”,这意味着什么呢?您真的认为对C ++中的单元测试提供更好的IDE支持是没有价值的吗?
马丁·巴

我的意思是,在类似c ++的语言上,系统无法自动为明显的陈述以外的任何事物创建测试
Martin Beckett

2
为什么不?是什么阻碍了插件自动动态生成vcproj文件,拉入我编写的测试文件文件和引用的生产文件并尝试运行该文件的麻烦?(只是做梦,但可以使它起作用。)
Martin Ba

2
我不确定是否可以跟随。显然,我必须自己编写测试。但是,与手动设置(和维护!)单独的测试项目文件相比,运行它们可能会容易得多。
马丁·巴

2
不,我没有提到测试代码,而是要获得运行测试代码和“它的”生产代码所需的项目/编译器脚手架。
马丁·巴

1

我无法评论C ++工具,因为我已经有20多年没有接触了(如今是.NET开发人员),而且我想这些天大多数工具都用于托管代码,但涉及技术……

正如其他人提到的那样,测试代码与生产代码始终在一个完全不同的项目/程序集中,是的,通常您必须自己维护该项目,尽管在VS IDE中当然不是一个大问题,因为您经常有多个项目。解决方案的一部分。

生产代码与TDD的编写必须有所不同。首先编写测试时,最终不得不将代码设计为可测试的。这本身就是其他主题,但是起初可能会花费一些时间,并且看起来非常令人沮丧,尤其是如果您的IDE /工具不能给您快速的反馈,那么花钱去运行命令行工具来运行测试只会带来破坏性的影响。

有许多使代码可测试的特定技术,但是其中大多数会分解成使小对象做不了什么,因此您可以孤立地测试它们,并能够将某些行为的测试版本注入到更复杂的环境中。对象。IOC框架在这里可以提供很多帮助。

您可能会觉得有用的一本书是;Michael Feathers,有效地使用旧版代码。它在示例中使用了多种语言,可以帮助您确定特定的方法来安全地适应最初并非可测试的代码/技术。

小警告:几年前,我从敏捷Kool-Aid喝醉了:D


注意:我已经Working Effectively with Legacy Code在办公桌上了:-)
Martin Ba

0

Maven在C ++中并未得到广泛使用(不过,它主要用于Java,但与语言无关),但是它是一个非常强大的工具,它允许您将所有内容保留在一个项目中(实际上,包括测试在内),这是推荐的。 Maven的方法)。我现在才建议这样做,因为到目前为止的答案似乎似乎不存在使用VS插件的替代方法。

搜索我发现的插件:

http://incubator.apache.org/npanday/

但看起来还不很成熟。使用Maven安装程序,您需要执行的所有操作均mvn test在命令行中运行。

如果你有兴趣,你可以了解它在这里和(之一)的C ++支持插件这里(Maven有一个插件架构,使一切是一个插件)。


0

框架建议:在我们的办公室,我们使用与Visual Studio集成的TestDriven.NET。单元测试类是用C ++ / CLI编写的,然后可以调出它们来行使您需要测试的任何本机代码。是的,C ++ / CLI类进入了自己的程序集,因此在解决方案中添加了“测试”项目。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.