diff options
author | Stef Walter <stef@memberwebs.com> | 2008-03-14 14:40:47 +0000 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2008-03-14 14:40:47 +0000 |
commit | 8865f7a28e40b82f98e944c8e7dbd67b56428bbc (patch) | |
tree | 1b51a96d8158b0758c304a7b72ff9c6d0cb2e533 /tests/cu-test/README | |
parent | 106dadfb63b371a1d5cf97ead46f975848e73786 (diff) |
Add unit tests
Diffstat (limited to 'tests/cu-test/README')
-rw-r--r-- | tests/cu-test/README | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/tests/cu-test/README b/tests/cu-test/README new file mode 100644 index 0000000..8bc1540 --- /dev/null +++ b/tests/cu-test/README @@ -0,0 +1,209 @@ +HOW TO USE + +You can use CuTest to create unit tests to drive your development +in the style of Extreme Programming. You can also add unit tests to +existing code to ensure that it works as you suspect. + +Your unit tests are an investment. They let you to change your +code and add new features confidently without worrying about +accidentally breaking earlier features. + + +LICENSING + +For details on licensing see license.txt. + + +GETTING STARTED + +To add unit testing to your C code the only files you need are +CuTest.c and CuTest.h. + +CuTestTest.c and AllTests.c have been included to provide an +example of how to write unit tests and then how to aggregate them +into suites and into a single AllTests.c file. Suites allow you +to put group tests into logical sets. AllTests.c combines all the +suites and runs them. + +You should not have to look inside CuTest.c. Looking in +CuTestTest.c and AllTests.c (for example usage) should be +sufficient. + +After downloading the sources, run your compiler to create an +executable called AllTests.exe. For example, if you are using +Windows with the cl.exe compiler you would type: + + cl.exe AllTests.c CuTest.c CuTestTest.c + AllTests.exe + +This will run all the unit tests associated with CuTest and print +the output on the console. You can replace cl.exe with gcc or +your favorite compiler in the command above. + + +DETAILED EXAMPLE + +Here is a more detailed example. We will work through a simple +test first exercise. The goal is to create a library of string +utilities. First, lets write a function that converts a +null-terminated string to all upper case. + +Ensure that CuTest.c and CuTest.h are accessible from your C +project. Next, create a file called StrUtil.c with these +contents: + + #include "CuTest.h" + + char* StrToUpper(char* str) { + return str; + } + + void TestStrToUpper(CuTest *tc) { + char* input = strdup("hello world"); + char* actual = StrToUpper(input); + char* expected = "HELLO WORLD"; + CuAssertStrEquals(tc, expected, actual); + } + + CuSuite* StrUtilGetSuite() { + CuSuite* suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, TestStrToUpper); + return suite; + } + +Create another file called AllTests.c with these contents: + + #include "CuTest.h" + + CuSuite* StrUtilGetSuite(); + + void RunAllTests(void) { + CuString *output = CuStringNew(); + CuSuite* suite = CuSuiteNew(); + + CuSuiteAddSuite(suite, StrUtilGetSuite()); + + CuSuiteRun(suite); + CuSuiteSummary(suite, output); + CuSuiteDetails(suite, output); + printf("%s\n", output->buffer); + } + + int main(void) { + RunAllTests(); + } + +Then type this on the command line: + + gcc AllTests.c CuTest.c StrUtil.c + +to compile. You can replace gcc with your favorite compiler. +CuTest should be portable enough to handle all Windows and Unix +compilers. Then to run the tests type: + + a.out + +This will print an error because we haven't implemented the +StrToUpper function correctly. We are just returning the string +without changing it to upper case. + + char* StrToUpper(char* str) { + return str; + } + +Rewrite this as follows: + + char* StrToUpper(char* str) { + char* p; + for (p = str ; *p ; ++p) *p = toupper(*p); + return str; + } + +Recompile and run the tests again. The test should pass this +time. + + +WHAT TO DO NEXT + +At this point you might want to write more tests for the +StrToUpper function. Here are some ideas: + +TestStrToUpper_EmptyString : pass in "" +TestStrToUpper_UpperCase : pass in "HELLO WORLD" +TestStrToUpper_MixedCase : pass in "HELLO world" +TestStrToUpper_Numbers : pass in "1234 hello" + +As you write each one of these tests add it to StrUtilGetSuite +function. If you don't the tests won't be run. Later as you write +other functions and write tests for them be sure to include those +in StrUtilGetSuite also. The StrUtilGetSuite function should +include all the tests in StrUtil.c + +Over time you will create another file called FunkyStuff.c +containing other functions unrelated to StrUtil. Follow the same +pattern. Create a FunkyStuffGetSuite function in FunkyStuff.c. +And add FunkyStuffGetSuite to AllTests.c. + +The framework is designed in the way it is so that it is easy to +organize a lot of tests. + +THE BIG PICTURE + +Each individual test corresponds to a CuTest. These are grouped +to form a CuSuite. CuSuites can hold CuTests or other CuSuites. +AllTests.c collects all the CuSuites in the program into a single +CuSuite which it then runs as a single CuSuite. + +The project is open source so feel free to take a peek under the +hood at the CuTest.c file to see how it works. CuTestTest.c +contains tests for CuTest.c. So CuTest tests itself. + +Since AllTests.c has a main() you will need to exclude this when +you are building your product. Here is a nicer way to do this if +you want to avoid messing with multiple builds. Remove the main() +in AllTests.c. Note that it just calls RunAllTests(). Instead +we'll call this directly from the main program. + +Now in the main() of the actual program check to see if the +command line option "--test" was passed. If it was then I call +RunAllTests() from AllTests.c. Otherwise run the real program. + +Shipping the tests with the code can be useful. If you customers +complain about a problem you can ask them to run the unit tests +and send you the output. This can help you to quickly isolate the +piece of your system that is malfunctioning in the customer's +environment. + +CuTest offers a rich set of CuAssert functions. Here is a list: + +void CuAssert(CuTest* tc, char* message, int condition); +void CuAssertTrue(CuTest* tc, int condition); +void CuAssertStrEquals(CuTest* tc, char* expected, char* actual); +void CuAssertIntEquals(CuTest* tc, int expected, int actual); +void CuAssertPtrEquals(CuTest* tc, void* expected, void* actual); +void CuAssertPtrNotNull(CuTest* tc, void* pointer); + +The project is open source and so you can add other more powerful +asserts to make your tests easier to write and more concise. +Please feel free to send me changes you make so that I can +incorporate them into future releases. + +If you see any errors in this document please contact me at +asimjalis@peakprogramming.com. + + +AUTOMATING TEST SUITE GENERATION + +make-tests.sh will grep through all the .c files in the current +directory and generate the code to run all the tests contained in +them. Using this script you don't have to worry about writing +AllTests.c or dealing with any of the other suite code. + + +CREDITS + +[02.23.2003] Dave Glowacki <dglo@hyde.ssec.wisc.edu> has added +(1) file name and line numbers to the error messages, (2) +AssertDblEquals for doubles, (3) Assert<X>Equals_Msg version of +all the Assert<X>Equals to pass in optional message which is +printed out on assert failure. |