第一次接触单元测试是在跟着别人做一个json解析器的时候,然后之后又接触了rspec做单元测试,所以趁着国庆假期,我想着把他们总结一下,目前我做的比较简单,另外google test 还没有接触,也想趁着假期简单的入个门。我也希望日后如果接触的更多能够单元测试的案例时,能够记录在这里。
首先是一个基本的框架,,该框架用来统计测test的数量,通过的数量,更多具体细节在test.c · jiawen/myjson
- static int main_ret = 0;
- static int test_count = 0; // 测试总数
- static int test_pass = 0; // 测试通过的数量
-
-
- // equality 是否相等 expect 期待的输出 actul实际的输出 format数据的格式
- #define EXPECT_EQ_BASE(equality, expect, actul, format) \
- do{ \
- test_count++; \
- if(equality){ \
- test_pass++; \
- } \
- else{ \
- fprintf(stderr, "[%s]->%d expect: " format" " "actual: " format"\n", __FILE__, __LINE__, expect, actul); \
- main_ret = 1; \
- } \
- }while(0)
- #define EXPECT_EQ_INT(expect, actul) EXPECT_EQ_BASE((expect == actul), expect, actul, "%d")
- #define EXPECT_EQ_DOUBLE(expect, actul) EXPECT_EQ_BASE((expect == actul), expect, actul, "%.17g")
- #define EXPECT_EQ_STRING(expect, actul, length)\
- EXPECT_EQ_BASE((sizeof(expect) -1 == length) &&(memcmp(expect, actul, length) == 0), expect, actul, "%s")
-
- // #define EXPECT_TRUE(actul) EXPECT_EQ_BASE(1 == actul, 1, actul, "%d")
- // #define EXPECT_FALSE(actul) EXPECT_EQ_BASE(0 == actul, 0, actul, "%d")
-
-
- #define EXPECT_TRUE(actual) EXPECT_EQ_BASE((actual) != 0, "true", "false", "%s")
- #define EXPECT_FALSE(actual) EXPECT_EQ_BASE((actual) == 0, "false", "true", "%s")
2.redis中的小的测试框架
- #ifndef __TESTHELP_H
- #define __TESTHELP_H
-
- int __failed_tests = 0;
- int __test_num = 0;
- #define test_cond(descr,_c) do { \
- __test_num++; printf("%d - %s: ", __test_num, descr); \
- if(_c) printf("PASSED\n"); else {printf("FAILED\n"); __failed_tests++;} \
- } while(0);
- #define test_report() do { \
- printf("%d tests, %d passed, %d failed\n", __test_num, \
- __test_num-__failed_tests, __failed_tests); \
- if (__failed_tests) { \
- printf("=== WARNING === We have failed tests here...\n"); \
- exit(1); \
- } \
- } while(0);
-
- #endif
rspec并不是出现的目的不是为了测试c语言,只是我看他的测试一些简单的东西还是比较容易的,所以想记录一下使用rspec测试c代码的过程。目前做的还比较简单,只是有过接触,当然我也不懂ruby,不过我也期待学习rspec。至于如何安装ruby和rspec,可以看看他的官网,我记得我是自己从源码编译的ruby,然后安装的。(这个有点不好用,不知道为什么,有时候代码可以通过,有时候不可以通过,但是make后就又可以通过了,奇了怪了)
- describe 'database' do
- before do
- `rm -rf test.db`
- end
-
- def run_script(commands)
- raw_output = nil
- IO.popen("./db", "r+") do |pipe|
- commands.each do |command|
- begin
- pipe.puts command
- rescue Errno::EPIPE
- break
- end
-
- end
- pipe.close_write
- raw_output = pipe.gets(nil)
-
- end
-
- raw_output.split("\n")
- end
-
- end
- describe 'database' do
- before do
- `rm -rf test.db`
- end
-
- def run_script(commands)
- raw_output = nil
- IO.popen("./db", "r+") do |pipe|
- commands.each do |command|
- begin
- pipe.puts command
- rescue Errno::EPIPE
- break
- end
-
- end
- pipe.close_write
- raw_output = pipe.gets(nil)
-
- end
-
- raw_output.split("\n")
- end
-
-
- it 'allows inserting strings that are the maximum length' do
- long_username = "a"*32
- long_email = "a"*255
- script = [
- "insert 1 #{long_username} #{long_email}",
- "select",
- ".exit",
- ]
- result = run_script(script)
- expect(result).to match_array([
- "db > Executed.",
- "db > 1 #{long_username} #{long_email}",
- "Executed.",
- "db > ",
- ])
- end
-
- it 'inserts and retireves a row' do
- result = run_script([
- "insert 1 user1 penson1@example.com",
- "select",
- ".exit",
- ])
- expect(result).to match_array([
- "db > Executed.",
- "db > 1 user1 penson1@example.com",
- "Executed.",
- "db > ",
- ])
-
- end
-
- end
下面是由AI生成的注释:
- # 定义一个方法,接受一个命令数组作为参数
- def run_script(commands)
- # 定义一个变量,用来存储脚本的输出
- raw_output = nil
- # 使用IO.popen方法,以读写模式打开一个进程,执行db脚本
- IO.popen("./db", "r+") do |pipe|
- # 遍历命令数组,逐个发送给脚本
- commands.each do |command|
- begin
- # 使用puts方法,将命令写入管道
- pipe.puts command
- rescue Errno::EPIPE
- # 如果发生管道断开的错误,终止循环
- # 这段代码非常有用,有时候会出现大量数据输入导致的pipe错误但是这段代码加入后没有问题了。
- break
- end
- end
- # 关闭管道的写入端
- pipe.close_write
- # 从管道的读取端获取所有的输出,赋值给raw_output变量
- raw_output = pipe.gets(nil)
- end
- # 将原始输出按换行符分割,返回一个数组
- raw_output.split("\n")
- end
基础的部分感觉与自定义的一样,等我具体的使用了在记录一下。