简体   繁体   English

基本单元测试和C,我该如何开始?

[英]Basic unit test and C, how do I get started?

After reading quite some threads here at StackOverflow, I have come to the conclusion that I should adopt to some form of test driven development/unit test (or at least explore the area). 在StackOverflow上阅读了相当多的一些主题之后,我得出结论,我应该采用某种形式的测试驱动开发/单元测试(或至少探索该领域)。

And since we are talking about c code under Linux, I decided to give check a try (I don't know if this is the right choice but if it's no good I can always try something else later on). 而且,由于我们是在谈论Linux下的C代码,我决定放弃检查尝试(我不知道这是否是正确的选择,但如果它没有好我可以尝试别的以后的东西)。

But since this concept of unit test and unit test frameworks is totally new to me, I started out to do some unit test on a really small test code (but I was totally lost anyway and it felt like I was missing something). 但是由于单元测试和单元测试框架的这个概念对我来说是全新的,所以我开始对一个非常小的测试代码进行一些单元测试(但我完全迷失了,感觉就像我错过了一些东西)。

This is what I have done so far, I created the following file: 这是我到目前为止所做的,我创建了以下文件:

  • main.c, a main that only calls a function called my_pow and prints the result. main.c,一个只调用一个名为my_pow的函数并打印结果的main。
  • my_pow.c, contains the function my_pow. my_pow.c,包含函数my_pow。
  • my_pow.h my_pow.h
  • my_pow_test.c, I figured that I should place the unit code for the my_pow function here. my_pow_test.c,我想我应该在这里放置my_pow函数的单元代码。

(So the "normal program" is the main.c, my_pow.c and my_pow.h.) (所以“普通程序”是main.c,my_pow.c和my_pow.h。)

This is my_pow.c 这是my_pow.c


#include "my_pow.h"
int my_pow(int a, int b)
{
    return (a*b);
}

Then I figured that in my_pow_test.c I put something like this: 然后我想在my_pow_test.c中我放了这样的东西:


#include <check.h>
#include "my_pow.h"

START_TEST (test_my_pow)
{
    /* unit test code */
}
END_TEST

//do I need some sort off main here that calls test_my_pow?

This is basically the same as in the check manual chapter 3.1, but still not.... 这基本上与检查手册第3.1章中的相同,但仍然没有....

Could someone please push me in the right direction? 有人可以请我朝正确的方向努力吗?

Thanks Johan 谢谢约翰


Update: No reason why I tried to use check I just thought I should start somewhere, maybe CUnit is a better choice (I think I would try that as well and then make a educated choice). 更新:没有理由我尝试使用支票我只是认为我应该从某个地方开始,也许CUnit是一个更好的选择(我想我也会尝试这个,然后做出有根据的选择)。

Update: Thanks @philippe for indirectly pointing out that the on-line documentation is only half of the truth, the example code that clarifies what the documentation talks about was already installed with the check package. 更新:感谢@philippe间接指出在线文档只是事实的一半,澄清文档所述内容的示例代码已经与check包一起安装。 In the Ubuntu case /usr/share/doc/check/example/tests/ 在Ubuntu案例中/ usr / share / doc / check / example / tests /

Update: The code example was created so that you started out by looking at his first version, then the second one etc etc. So that you could follow how he creates a very basic test case/code from nothing up to something that is useful in a traditional TTD way. 更新:代码示例已创建,以便您通过查看他的第一个版本,然后是第二个版本等开始。这样您就可以了解他如何创建一个非常基本的测试用例/代码,从无到有用的东西传统的TTD方式。

And since my code was broken and I wanted the unit test to prove this, I cheated a little and tested against the real pow function. 而且由于我的代码被破坏了,我希望单元测试证明这一点,我作了一点欺骗并测试了真正的功能。 Something like this: 像这样的东西:


START_TEST (test_my_pow1)
{
    int resultat = my_pow(3,3);
    int math     = pow(3,3);
    fail_unless ( resultat == math,
           "Error on 3^3 != %d (%d)",math, resultat);
}

However in the future I will not reproduce what is already in the stdlibs :-) 但是将来我不会重现stdlibs中的内容:-)


Related: 有关:

taken from searching [c] [unit-testing] . 取自搜索[c] [unit-testing]

You created a first test case. 您创建了第一个测试用例。 Now you need to create a test suite (a group of test cases) and a runner . 现在您需要创建一个测试套件 (一组测试用例)和一个跑步者

I would recommend you try to compile their example first to validate your environment, although their documentation introduces new code via diff (source patch) which I do not find very convenient. 我建议你首先尝试编译他们的例子以验证你的环境,虽然他们的文档通过diff(源补丁)引入了新的代码,我觉得这并不方便。


If ever you decide to try with another framework ( minunit came to my mind immediately), I can point you to a " tutorial ". 如果您决定尝试使用另一个框架(我立刻想到了minunit ),我可以指向一个“ 教程 ”。

I'd be more inclined to go with CUnit which is part of the X-Unit series of test frameworks. 我更倾向于使用CUnit ,它是X-Unit系列测试框架的一部分。

It's scalable to large suites of tests and has been in use for many years, hence mature. 它可以扩展到大型测试套件,并且已经使用了很多年,因此已经成熟。

Any reason why you didn't go with CUnit? 您没有使用CUnit的任何理由?

HTH HTH

cheers, 干杯,

Rob

I've been using dejagnu for years and love it. 我多年来一直在使用dejagnu而且喜欢它。

I started using it for embedded development because it supports very well the concept that the machine on which you're running the test program may be different than the machine on which you build the test program. 我开始将它用于嵌入式开发,因为它非常支持您运行测试程序的机器可能与构建测试程序的机器不同的概念。 A consequence of this is that testing code on multiple platforms is also well supported. 这样做的结果是,在多个平台上测试代码也得到了很好的支持。 Not sure if that's important. 不确定这是否重要。 The gcc testsuite uses it. gcc测试套件使用它。 I use it for desktop development as well. 我也用它来进行桌面开发。

The basic idea with dejagnu is that you dejagnu的基本想法就是你

  • copy the test program to the "target" (which for local testing could be the ~/tmp directory) 将测试程序复制到“目标”(本地测试可以是〜/ tmp目录)
  • start the test program 启动测试程序
  • print stuff to the console (which acts as input to the test program) 将东西打印到控制台(作为测试程序的输入)
  • parse the output from the test program and match it with what you expect 解析测试程序的输出并将其与您期望的匹配
  • decide whether that output means pass or fail 判断输出是通过还是失败

Once you've got the test program and the test scripts written, you end up doing something like this: 一旦你完成了测试程序并编写了测试脚本,你最终会做这样的事情:

$ runtest
                === foo Summary ===

# of expected passes            42
foo-test built Thu Jan 15 20:09:19 PST 2009
foo-test version 0.0.0.1
runtest completed at Sun Jan 18 08:29:13 2009

The way I get there for testing a library named foo is: 我到那里测试一个名为foo的库的方法是:

  • assume the source and include files for the library are in ~/src/foo 假设库的源文件和包含文件位于〜/ src / foo中
  • create a directory named ~/src/foo/testsuite 创建一个名为〜/ src / foo / testsuite的目录
  • write a test program named foo-test.c that has a main() that 编写一个名为foo-test.c的测试程序,它有一个main()
    • processes command line args 处理命令行args
    • - prints a prompt and sits in a loop processing "commands" where I define a command to test each function in my library. - 打印一个提示并坐在循环处理“命令”中,我在其中定义一个命令来测试我的库中的每个函数。 This is sort of like a command shell but specific to the library. 这有点像命令shell,但特定于库。 For something like my_pow I'd define the command to take 2 args. 对于像my_pow这样的东西我定义了2个args的命令。
    • write a dejagnu (which is another layer on top of Expect (http://expect.nist.gov/, which is itself a layer on top of Tcl (http://www.tcl.tk/) function called my_pow that: 写一个dejagnu(这是Expect之上的另一层(http://expect.nist.gov/,它本身就是一个名为my_pow的Tcl(http://www.tcl.tk/)函数之上的层:
      • takes two arguments 有两个论点
      • calculates the expected result (in Tcl) 计算预期结果(在Tcl中)
      • sends "my_pow " to the console 将“my_pow”发送到控制台
      • parses the output of the my_pow command from foo-test 从foo-test解析my_pow命令的输出
      • determines whether the actual result matches the expected result 确定实际结果是否与预期结果匹配
      • calls the appropriate dejagnu function (pass or fail) 调用适当的dejagnu函数(通过或失败)

Sounds hard, but it's not. 听起来很难,但事实并非如此。 It takes a little while to decide how much work to do in foo-test vs. how much to do in Tcl. 需要一点时间来决定在foo-test中要做多少工作与在Tcl中做多少工作。 I end up using a fair amount of shell (eg bash) functionality to do things like copy files to temp directories or look at the log files that my programs generate. 我最终使用相当数量的shell(例如bash)功能来执行诸如将文件复制到临时目录或查看我的程序生成的日志文件之类的操作。 So you end up getting good at all this stuff. 所以你最终会擅长这些东西。

As far as references, there's one book on Expect that I'd say is a requirement for diving into this: http://oreilly.com/catalog/9781565920903/index.html . 至于参考资料,有一本关于Expect的书我想说是潜入这个要求: http//oreilly.com/catalog/9781565920903/index.html
Between that and an online Tcl command reference http://www.tcl.tk/man/tcl8.4/TclCmd/contents.htm and FAQ ( http://www.psg.com/~joem/tcl/faq.html ), you're pretty much there. 在那之间和在线Tcl命令参考http://www.tcl.tk/man/tcl8.4/TclCmd/contents.htm和FAQ( http://www.psg.com/~joem/tcl/faq.html) ),你几乎就在那里。

Good luck. 祝好运。

-DB -D B

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM