Converting README to markdown.
This commit is contained in:
222
README.md
Normal file
222
README.md
Normal file
@@ -0,0 +1,222 @@
|
||||
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
|
||||
|
||||
On Unix you should type:
|
||||
|
||||
gcc AllTests.c CuTest.c CuTestTest.c
|
||||
./a.out
|
||||
|
||||
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@gmail.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.
|
Reference in New Issue
Block a user