• c单元语言测试--自定义代码、rspec 和Google test


    一、简介

            第一次接触单元测试是在跟着别人做一个json解析器的时候,然后之后又接触了rspec做单元测试,所以趁着国庆假期,我想着把他们总结一下,目前我做的比较简单,另外google test 还没有接触,也想趁着假期简单的入个门。我也希望日后如果接触的更多能够单元测试的案例时,能够记录在这里。

    二、自定义代码

    1.基本框架

    首先是一个基本的框架,,该框架用来统计测test的数量,通过的数量,更多具体细节在test.c · jiawen/myjson

    1. static int main_ret = 0;
    2. static int test_count = 0; // 测试总数
    3. static int test_pass = 0; // 测试通过的数量
    4. // equality 是否相等 expect 期待的输出 actul实际的输出 format数据的格式
    5. #define EXPECT_EQ_BASE(equality, expect, actul, format) \
    6. do{ \
    7. test_count++; \
    8. if(equality){ \
    9. test_pass++; \
    10. } \
    11. else{ \
    12. fprintf(stderr, "[%s]->%d expect: " format" " "actual: " format"\n", __FILE__, __LINE__, expect, actul); \
    13. main_ret = 1; \
    14. } \
    15. }while(0)

    2.测试具体类型

    1. #define EXPECT_EQ_INT(expect, actul) EXPECT_EQ_BASE((expect == actul), expect, actul, "%d")
    2. #define EXPECT_EQ_DOUBLE(expect, actul) EXPECT_EQ_BASE((expect == actul), expect, actul, "%.17g")
    3. #define EXPECT_EQ_STRING(expect, actul, length)\
    4. EXPECT_EQ_BASE((sizeof(expect) -1 == length) &&(memcmp(expect, actul, length) == 0), expect, actul, "%s")
    5. // #define EXPECT_TRUE(actul) EXPECT_EQ_BASE(1 == actul, 1, actul, "%d")
    6. // #define EXPECT_FALSE(actul) EXPECT_EQ_BASE(0 == actul, 0, actul, "%d")
    7. #define EXPECT_TRUE(actual) EXPECT_EQ_BASE((actual) != 0, "true", "false", "%s")
    8. #define EXPECT_FALSE(actual) EXPECT_EQ_BASE((actual) == 0, "false", "true", "%s")

    2.redis中的小的测试框架 

    1. #ifndef __TESTHELP_H
    2. #define __TESTHELP_H
    3. int __failed_tests = 0;
    4. int __test_num = 0;
    5. #define test_cond(descr,_c) do { \
    6. __test_num++; printf("%d - %s: ", __test_num, descr); \
    7. if(_c) printf("PASSED\n"); else {printf("FAILED\n"); __failed_tests++;} \
    8. } while(0);
    9. #define test_report() do { \
    10. printf("%d tests, %d passed, %d failed\n", __test_num, \
    11. __test_num-__failed_tests, __failed_tests); \
    12. if (__failed_tests) { \
    13. printf("=== WARNING === We have failed tests here...\n"); \
    14. exit(1); \
    15. } \
    16. } while(0);
    17. #endif

     

    三、rspec测试

            rspec并不是出现的目的不是为了测试c语言,只是我看他的测试一些简单的东西还是比较容易的,所以想记录一下使用rspec测试c代码的过程。目前做的还比较简单,只是有过接触,当然我也不懂ruby,不过我也期待学习rspec。至于如何安装ruby和rspec,可以看看他的官网,我记得我是自己从源码编译的ruby,然后安装的。(这个有点不好用,不知道为什么,有时候代码可以通过,有时候不可以通过,但是make后就又可以通过了,奇了怪了)

    1.基本结构

    1. describe 'database' do
    2. before do
    3. `rm -rf test.db`
    4. end
    5. def run_script(commands)
    6. raw_output = nil
    7. IO.popen("./db", "r+") do |pipe|
    8. commands.each do |command|
    9. begin
    10. pipe.puts command
    11. rescue Errno::EPIPE
    12. break
    13. end
    14. end
    15. pipe.close_write
    16. raw_output = pipe.gets(nil)
    17. end
    18. raw_output.split("\n")
    19. end
    20. end

    2.测试用例

    1. describe 'database' do
    2. before do
    3. `rm -rf test.db`
    4. end
    5. def run_script(commands)
    6. raw_output = nil
    7. IO.popen("./db", "r+") do |pipe|
    8. commands.each do |command|
    9. begin
    10. pipe.puts command
    11. rescue Errno::EPIPE
    12. break
    13. end
    14. end
    15. pipe.close_write
    16. raw_output = pipe.gets(nil)
    17. end
    18. raw_output.split("\n")
    19. end
    20. it 'allows inserting strings that are the maximum length' do
    21. long_username = "a"*32
    22. long_email = "a"*255
    23. script = [
    24. "insert 1 #{long_username} #{long_email}",
    25. "select",
    26. ".exit",
    27. ]
    28. result = run_script(script)
    29. expect(result).to match_array([
    30. "db > Executed.",
    31. "db > 1 #{long_username} #{long_email}",
    32. "Executed.",
    33. "db > ",
    34. ])
    35. end
    36. it 'inserts and retireves a row' do
    37. result = run_script([
    38. "insert 1 user1 penson1@example.com",
    39. "select",
    40. ".exit",
    41. ])
    42. expect(result).to match_array([
    43. "db > Executed.",
    44. "db > 1 user1 penson1@example.com",
    45. "Executed.",
    46. "db > ",
    47. ])
    48. end
    49. end

    下面是由AI生成的注释:

    1. # 定义一个方法,接受一个命令数组作为参数
    2. def run_script(commands)
    3. # 定义一个变量,用来存储脚本的输出
    4. raw_output = nil
    5. # 使用IO.popen方法,以读写模式打开一个进程,执行db脚本
    6. IO.popen("./db", "r+") do |pipe|
    7. # 遍历命令数组,逐个发送给脚本
    8. commands.each do |command|
    9. begin
    10. # 使用puts方法,将命令写入管道
    11. pipe.puts command
    12. rescue Errno::EPIPE
    13. # 如果发生管道断开的错误,终止循环
    14. # 这段代码非常有用,有时候会出现大量数据输入导致的pipe错误但是这段代码加入后没有问题了。
    15. break
    16. end
    17. end
    18. # 关闭管道的写入端
    19. pipe.close_write
    20. # 从管道的读取端获取所有的输出,赋值给raw_output变量
    21. raw_output = pipe.gets(nil)
    22. end
    23. # 将原始输出按换行符分割,返回一个数组
    24. raw_output.split("\n")
    25. end

    四、google test

    基础的部分感觉与自定义的一样,等我具体的使用了在记录一下。

  • 相关阅读:
    EasyExcel表头校验方法
    JAVA毕业设计web家教信息服务平台设计与实现计算机源码+lw文档+系统+调试部署+数据库
    在自己电脑上的idea运行java web项目 如何用外网访问
    本地Win10用SSH登录腾讯轻量云Ubuntu20.04,允许root用密码远程 登录
    js:Browserslist用特定语句查询浏览器列表的工具与Babel和Postcss配置使用
    react dispatch不生效的坑
    NC202475 树上子链
    linux systemd start stop enable disable命令区别
    【Python】WebUI自动化—Selenium的下载和安装、基本用法、项目实战(16)
    1.8 逻辑运算(Python)
  • 原文地址:https://blog.csdn.net/weixin_46430043/article/details/133343580