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

一、简介

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

二、自定义代码

1.基本框架

首先是一个基本的框架,,该框架用来统计测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)

2.测试具体类型

#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测试

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

1.基本结构

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

2.测试用例

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 [email protected]",
            "select",
            ".exit",
        ])
        expect(result).to match_array([
            "db > Executed.",
            "db > 1 user1 [email protected]",
            "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

四、google test

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

你可能感兴趣的:(c语言)