MSDN Magazine - February 2008 - (Page 77) Command textbox. For Command Arguments, type “$(TargetPath)” (include the double quotes). To verify everything in your project is set up correctly, you can add DummyTest.cpp to your project and build. The project should build, but if you’ve typed in the false assertion line as presented, you’ll clearly see a test failure on that line. Now that the setup is out of the way, it’s time to look at the different ways of using WinUnit features to write tests. You may want to switch to WinUnitComplete.sln for the moment to follow along with my examples. The projects containing the examples are SampleLib and TestSampleLib. SampleLib is a static library that happens to contain exactly one class, BinaryNumber. TestSampleLib is a test DLL that links with SampleLib.lib and includes tests for the BinaryNumber class along with a few other examples. General WinUnit test functions always begin with BEGIN_ TEST(TestName) and end with END_TEST. Within each test, one or more WIN_ASSERT macros are used in order to verify various bits of functionality. My example BinaryNumber class has two constructors. One takes an unsigned short, and one takes a string comprising the characters 1 and 0. I intend for the constructors to result in equivalent objects when passed equivalent values. So I may have a test like this: BEGIN_TEST(BinaryNumberConstructorsShouldBeEquivalent) { unsigned short numericValue = 7; BinaryNumber bn1(numericValue); BinaryNumber bn2(“111”); WIN_ASSERT_EQUAL(bn1.NumericValue, bn2.NumericValue, _T(“Both values should be %u.”), numericValue); WIN_ASSERT_STRING_EQUAL(bn1.StringValue, bn2.StringValue); } END_TEST BinaryNumber bn1(s); BinaryNumber bn2(s); WIN_ASSERT_THROWS(bn1 + bn2, BinaryNumber::IntegerOverflowException) } END_TEST This test will fail if either of the two assert lines is false. Notice that the WIN_ASSERT_EQUAL macro in this example is passed the two values being compared, plus two extra arguments. These comprise an informational message that will be shown if the assert fails. All WIN_ASSERT macros take an optional printf-style format string and arguments for this purpose. Since I implemented operator ‘==’ for the BinaryNumber class, I can also use the following construction (which is what I have in my sample file, BinaryNumberTest.cpp): BEGIN_TEST( BinaryNumberConstructorsShouldBeEquivalent) { BinaryNumber bn1(7); BinaryNumber bn2(“111”); WIN_ASSERT_EQUAL(bn1, bn2); } END_TEST Here’s a different type of assert, WIN_ ASSERT_THROWS. Suppose I use exceptions for my error handling in my production code, and I want to force an error condition in my test to ensure that the proper exception is thrown. I might make a test like this: BEGIN_TEST( BinaryNumberPlusRecognizesIntegerOverflow) { unsigned short s = USHRT_MAX / 2 + 1; I know that my BinaryNumber class only holds an unsigned short. I also know that the operator ‘+’ should detect when I’m trying to add two numbers together that are too big. WIN_ASSERT_ THROWS takes an expression that should throw a C++ exception, along with the exception type itself. The test fails if the exception is not thrown. Figure 4 lists the WIN_ WinUnit does not inherently ASSERT macros available have the concept of groups in WinUnit.h, as well as one of tests. The way to tell non-assert, WIN_TRACE, WinUnit to run a subset of that can be used to provide tracing through the tests in a project is with the OutputDebugString API -p (prefix) option. function in your tests. Note that for either WIN_ ASSERT_EQUAL or WIN_ASSERT_NOT_EQUAL, if a numeric literal is passed in as one of the values and an unsigned number as the other, you’ll get a signed/unsigned mismatch, as numeric literal integers always template-match to int. To get around this, postfix numeric literals with ‘U’ so they will match as unsigned. All asserts take an optional printf-style format string, plus arguments. If _UNICODE is defined, these message strings will be wchar_t*, so use the _T (“”) macro around the format strings, or L”” if you’re building Unicode-only. You may have noticed that my test names begin with the name of the class being tested, followed by the name or description of the method being tested, followed by a partial sentence describing what the test is supposed to show. This convention serves two purposes. First, it is an easy way to make clear exactly what you’re trying to test, which can be useful when looking at test output. Second, it’s a way to group tests to be run together at varying levels of granularity. WinUnit does not inherently have the concept of groups of tests, as do its .NET Framework-based equivalents. The way to tell WinUnit to run a subset of tests in a project is with the -p (prefix) option. You specify a prefix string, and WinUnit will run all the tests whose names start with that string. By naming your tests with words ordered least to most specific, you will be able to easily run related groups of tests from the command line. Fixtures: Setup and Teardown Figure 3 Adding WinUnit to External Tools In real life, the things you’re trying to test are often not as simple as the examples I’ve shown so far. There may be cases where several setup steps are required to get to the point where you can actually execute the functionality you want to verify. WinUnit february2008 77
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.