C Language Unit Test framework--cutest

Source: Internet
Author: User
Tags assert sprintf

1. Introduction

Cutest is a tiny C-Language Unit test box, one of the most concise test frameworks I've seen so far, with only 2 files, cutest.c and CuTest.h, all of which add up to less than 1000 lines of code. Perfectly formed, test construction, test management, test statements are all included.

2, cutest analysis 2.1 Assertions

Whether a test case is implemented by falling into code is a comparison between the test value and the expected value, which is used to assert.

#defineCuassertstrequals (TC,EX,AC) cuassertstrequals_linemsg ((TC), __file__,__line__,null, (ex), (AC))#defineCuassertstrequals_msg (TC,MS,EX,AC) cuassertstrequals_linemsg ((TC), __file__,__line__, (ms), (ex), (AC))#defineCuassertintequals (TC,EX,AC) cuassertintequals_linemsg ((TC), __file__,__line__,null, (ex), (AC))#defineCuassertintequals_msg (TC,MS,EX,AC) cuassertintequals_linemsg ((TC), __file__,__line__, (ms), (ex), (AC))#defineCuassertdblequals (TC,EX,AC,DL) cuassertdblequals_linemsg ((TC), __file__,__line__,null, (ex), (AC), (DL))#defineCuassertdblequals_msg (TC,MS,EX,AC,DL) cuassertdblequals_linemsg ((TC), __file__,__line__, (ms), (ex), (AC), (DL))#defineCuassertptrequals (TC,EX,AC) cuassertptrequals_linemsg ((TC), __file__,__line__,null, (ex), (AC))#defineCuassertptrequals_msg (TC,MS,EX,AC) cuassertptrequals_linemsg ((TC), __file__,__line__, (ms), (ex), (AC))
......
......

Take the digital test as an example cuassertintequals, in fact, is now:

voidCuassertintequals_linemsg (cutest* TC,Const Char* File,intLineConst Char*message,intExpected,intActual) {    CharBuf[string_max]; if(expected = = Actual)return; sprintf (BUF,"expected <%d> but is <%d>", expected, actual); Cufail_line (TC, file, line, message, buf);}

If the test succeeds, the next step will be quiet and return this function from return.
Most of the testing framework philosophy and Linux philosophy is very similar, small is beautiful, less is good, no exception will not disturb the user.
In the event of an error, the error message is saved, as well as the file path/filename/function name, and line number.

" expected <%d> but is <%d> " , expected, actual); Cufail_line (TC, file, line, message, buf);

Further down, the above function is implemented: Stitching the error message to a string and passing it to the Cufailinternal function. It is easy to find from the Cufailinternal function name that this function is the core of the real error return.
1) Append the function name and line number to the string after the user error message. Implemented by the Custringinsert statement.
2) Error flag, tc->failed position.
3) The complete error message refers to the message pointer assigned to the test.
4) return, long jump.

voidCufail_line (cutest* TC,Const Char* File,intLineConst Char* Message2,Const Char*message) {custringstring; Custringinit (&string); if(Message2! =NULL) {Custringappend (&string, Message2); Custringappend (&string,": "); } custringappend (&string, message); Cufailinternal (TC, file, line,&string);}Static voidCufailinternal (cutest* TC,Const Char* File,intLine, custring*string){    CharBuf[huge_string_len]; sprintf (BUF,"%s:%d:", file, line); Custringinsert (string, BUF,0); TC->failed =1; TC->message =string-buffer; if(Tc->jumpbuf! =0) longjmp (* (TC-&GT;JUMPBUF),0);}

Here, a wrong test is returned from LONGJMP.

2.2 Tested organizations

No matter how subtle a test is, a logical test function is required, which is the test case. For example, the following test case.
Prototype of the function to be tested:

int AddInt (intint b);

Test Case:

void test_add (cutest* tc) {   "\r\ntest not pass"2 = = AddInt ( 1,0);} Cusuite* Testadd (void) {    cusuite* Suite = cusuitenew ();    Suite_add_test (suite, test_add);     return Suite;}

If there are many tests, the management of the test group is used. This is the management of test case, called Suite in cutest.

cusuite* cugetsuite (void) {    cusuite* Suite = cusuitenew ();    Suite_add_test (suite, Testcustringappendformat);    Suite_add_test (suite, testcustrcopy);    Suite_add_test (suite, testfail);    Suite_add_test (suite, testassertstrequals);    Suite_add_test (suite, testassertstrequals_null);     return Suite;}

In general, Suite is a collection of tests that actually call the Cusuiteadd function.

#define Suite_add_test (suite,test)    cusuiteadd (SUITE, Cutestnew (#TEST, TEST))

Expand with a macro, #TEST等价于TEST内容转换为字符串, Cutestnew (#TEST, TEST) is a magical use of macros. This function is to add the case to the specific list of testsuite.

void Cusuiteadd (cusuite* testSuite, cutest *testCase) {    assert (testSuite->count < max_test_cases);    TestSuite->list[testsuite->count] = testCase;    TestSuite->count++;}

The above is a class of tests, using the Suite function suite_add_test to achieve the collation management of multiple test functions. So when you have multiple functions, how do you plan to do it, and you need to add your suite to your suite. Finally, a reference to the upper interface is provided for a total suite.

    cusuite* Suite = cusuitenew ();    Cusuiteaddsuite (Suite, Cugetsuite ());    Cusuiteaddsuite (Suite, Custringgetsuite ());    Cusuiteaddsuite (Suite, Testadd ());
2.3 Run of the test

The test case forms the test group--suite, and then multiple test groups can be combined into one test group. The execution of a test group is to iterate through the array and execute each test case inside.

void Cusuiterun (cusuite* testSuite) {    int  i;      for 0 ; i < Testsuite->count; + +i)    {        cutest* testCase = testsuite->list[i];        Cutestrun (testCase);         if 1 ; }    }}

The execution of the test is done by Cutestrun, which is still to lay the jump breakpoint--setjmp (BUF), and then run the test case, if there is no error in the test, exit silently, otherwise log an error message, and then longjmp return to if (setjmp (buf) = = 0 A row, in the Cusuiterun, will count the number of error case, so that after all case runs, the output summary information is used.

void Cutestrun (cutest* tc) {    jmp_buf buf;    TC->jumpbuf = &buf;     if 0 )    {        tc1;        (TC,function) (TC);    }    TC0;}

The above function, the call of the test function is very obscure, is the (tc->function) (TC) statement completed. The prototype of the test case is:

void (*testfunction) (cutest *); struct cutest{    Char* name;    testfunction function;     int failed;     int ran;     Const Char* message;     *jumpbuf;};

So the function points to the specific test case.
The specific implementation is: The first step is to create a test case, the cutest* TC. The parameter function passed in cutestnew is a reference pointer to the specific test case functions.

cutest* cutestnew (constChar* name, testfunction function) {    cutest* tc = Cu_alloc ( cutest);    Cutestinit (TC, name, function);     return TC;}

The second step is to test case initialization and assign the Funciton reference pointer to cutest* t->function. So the (tc->function) (TC) statement is equivalent to calling the test case function body directly.

void Const Char* name, testfunction function) {    t->name = custrcopy (name);    T0;    T0;    T->message = NULL;    T->function = function;    T->jumpbuf = NULL;}
3. Cutest instances

Here is a simple example that includes a test case, a test group, and a test execution.
1) test Case

void test_add (cutest* tc) {   "\r\ntest not pass"21  1);}

2) test Group Suite

cusuite* Testadd (void) {    cusuite* Suite = cusuitenew ();    Suite_add_test (suite, test_add);     return Suite;}

3) test Project Structure organization

void Main () {    runalltests ();    GetChar ();} void Runalltests (void) {    *output = custringnew ();    Cusuite* Suite = cusuitenew ();    Cusuiteaddsuite (Suite, Testadd ());    Cusuiterun (suite);    Cusuitesummary (suite, output);    Cusuitedetails (suite, output);    printf ("%s\n", output->buffer);}

C Language Unit Test framework--cutest

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.