【问题标题】:Basic unit test and C, how do I get started?基本单元测试和 C,我该如何开始?
【发布时间】:2009-01-17 11:03:52
【问题描述】:

在 StackOverflow 上阅读了相当多的帖子后, 我已经得出结论,我应该采用某种形式的 测试驱动开发/单元测试(或至少探索该领域)。

既然我们在讨论 Linux 下的 c 代码, 我决定试试check (我不知道这是否是正确的选择,但如果不好,我可以稍后再尝试其他方法)。

但是由于单元测试和单元测试框架的概念对我来说是全新的, 我开始对一个非常小的测试代码进行一些单元测试(但无论如何我完全迷失了,感觉好像我错过了一些东西)。

这是我到目前为止所做的,我创建了以下文件:

  • main.c,一个只调用名为 my_pow 的函数并打印结果的 main。
  • my_pow.c,包含函数 my_pow。
  • my_pow.h
  • my_pow_test.c,我想我应该把my_pow函数的单元代码放在这里。

(所以“正常程序”是main.c、my_pow.c和my_pow.h。)

这是 my_pow.c

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

然后我发现在 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?

这与the check manual第3.1章基本相同, 但还是不行……

有人可以把我推向正确的方向吗?

谢谢 约翰


更新:我没有理由尝试使用 check 我只是认为我应该从某个地方开始, 也许 CUnit 是一个更好的选择(我想我也会尝试,然后做出明智的选择)。

更新:感谢@philippe 间接指出在线文档只是事实的一半, 阐明文档所讨论内容的示例代码已与 check 包一起安装。 在 Ubuntu 案例中 /usr/share/doc/check/example/tests/

更新:创建代码示例是为了让您从查看他的第一个版本开始, 然后是第二个等等。这样您就可以了解他如何创建一个非常基本的测试用例/代码,从无到有,在传统的 TTD 方式中有用。

由于我的代码被破坏了,我希望单元测试来证明这一点, 我作弊了一点,并针对真正的 pow 函数进行了测试。 像这样:

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); }

但是在未来我不会复制标准库中已有的内容:-)


相关:

取自搜索[c] [unit-testing]。

【问题讨论】:

  • 你知道 pow(a,b) != a*b 吗? ;-)
  • @Aif,我猜他知道。但是要了解和学习单元测试的强大功能,从一个有缺陷的函数开始并不是一个坏主意。

标签: c linux unit-testing tdd check-framework


【解决方案1】:

您创建了第一个测试用例。现在你需要create a test suite(一组测试用例)和一个runner。

我建议您首先尝试编译their example 以验证您的环境,尽管他们的文档通过 diff(源补丁)引入了新代码,我觉得这不太方便。


如果您决定尝试使用另一个框架(minunit 立即出现在我的脑海中),我可以为您指出“tutorial”。

【讨论】:

  • 上面的链接不再是最新的了...改用这些链接:test suite, runner
【解决方案2】:

我更倾向于使用 CUnit,它是 X-Unit 系列测试框架的一部分。

它可以扩展到大型测试套件,并且已经使用了很多年,因此很成熟。

您为什么不选择 CUnit?

HTH

干杯,

罗伯

【讨论】:

    【解决方案3】:

    我多年来一直在使用dejagnu,并且喜欢它。

    我开始将它用于嵌入式开发,因为它很好地支持了运行测试程序的机器可能与构建测试程序的机器不同的概念。这样做的结果是,在多个平台上测试代码也得到了很好的支持。不确定这是否重要。 gcc 测试套件使用它。我也将它用于桌面开发。

    dejagnu 的基本理念是你

    • 将测试程序复制到“目标”(本地测试可以是 ~/tmp 目录)
    • 启动测试程序
    • 将内容打印到控制台(作为测试程序的输入)
    • 解析测试程序的输出并将其与您期望的匹配
    • 决定输出是通过还是失败

    一旦你编写好了测试程序和测试脚本,你最终会做这样的事情:

    $ 运行测试
                    === foo 总结 ===
    
    # 预期通过次数 42
    foo-test 于 2009 年 1 月 15 日星期四 20:09:19 PST 建成
    foo-test 版本 0.0.0.1
    运行测试于 2009 年 1 月 18 日星期日 08:29:13 完成

    我在那里测试一个名为 foo 的库的方法是:

    • 假设库的源文件和包含文件在 ~/src/foo 中
    • 创建一个名为 ~/src/foo/testsuite 的目录
    • 编写一个名为 foo-test.c 的测试程序,它有一个 main()
      • 处理命令行参数
      • - 打印一个提示并位于一个循环处理“命令”中,我在其中定义了一个命令来测试我的库中的每个函数。这有点像命令外壳,但特定于库。对于 my_pow 之类的东西,我将命令定义为采用 2 个参数。
      • 编写一个dejagnu(它是Expect (http://expect.nist.gov/) 之上的另一层,它本身就是Tcl (http://www.tcl.tk/) 之上的一层)函数调用my_pow :
        • 接受两个参数
        • 计算预期结果(在 Tcl 中)
        • 将“my_pow”发送到控制台
        • 从 foo-test 解析 my_pow 命令的输出
        • 判断实际结果是否与预期结果相符
        • 调用相应的 dejagnu 函数(通过或失败)

    听起来很难,但事实并非如此。决定在 foo-test 中做多少工作与在 Tcl 中做多少工作需要一点时间。我最终使用了大量的 shell(例如 bash)功能来执行诸如将文件复制到临时目录或查看我的程序生成的日志文件之类的事情。所以你最终会擅长所有这些东西。

    就参考资料而言,有一本关于 Expect 的书我想说是深入研究的必要条件:http://oreilly.com/catalog/9781565920903/index.html。
    在此和在线 Tcl 命令参考 http://www.tcl.tk/man/tcl8.4/TclCmd/contents.htm 和常见问题解答 (http://www.psg.com/~joem/tcl/faq.html) 之间,您几乎就在那里。

    祝你好运。

    -数据库

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-20
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-12
      • 1970-01-01
      相关资源
      最近更新 更多