Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1061855
  • 博文数量: 264
  • 博客积分: 6005
  • 博客等级: 大校
  • 技术积分: 2798
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-08 20:15
文章分类

全部博文(264)

文章存档

2011年(42)

2010年(213)

2009年(4)

2008年(2)

2007年(3)

分类: C/C++

2010-01-15 00:03:37

  1. Tests should be portable and reusable. The open-source community has a lot of code that is platform-neutral, its tests should also be platform-neutral. Google C++ Testing Framework works on different OSes, with different compilers (gcc, MSVC, and others), with or without exceptions, so Google C++ Testing Framework tests can easily work with a variety of configurations. (Note that the current release only contains build scripts for Linux - we are actively working on scripts for other platforms.)
  2. When tests fail, they should provide as much information about the problem as possible. Google C++ Testing Framework doesn't stop at the first test failure. Instead, it only stops the current test and continues with the next. You can also set up tests that report non-fatal failures after which the current test continues. Thus, you can detect and fix multiple bugs in a single run-edit-compile cycle.
  3. The testing framework should liberate test writers from housekeeping chores and let them focus on the test content. Google C++ Testing Framework automatically keeps track of all tests defined, and doesn't require the user to enumerate them in order to run them.

When using Google Test, you start by writing assertions, which are statements that check whether a condition is true. An assertion's result can be success, nonfatal failure, or fatal failure. If a fatal failure occurs, it aborts the current function; otherwise the program continues normally.

Google Test assertions are macros that resemble function calls. You test a class or function by making assertions about its behavior. When an assertion fails, Google Test prints the assertion's source file and line number location, along with a failure message. You may also supply a custom failure message which will be appended to Google Test's message.

The assertions come in pairs that test the same thing but have different effects on the current function. ASSERT_* versions generate fatal failures when they fail, and abort the current function. EXPECT_* versions generate nonfatal failures, which don't abort the current function. Usually EXPECT_* are preferred, as they allow more than one failures to be reported in a test. However, you should use ASSERT_* if it doesn't make sense to continue when the assertion in question fails.

Since a failed ASSERT_* returns from the current function immediately, possibly skipping clean-up code that comes after it, it may cause a space leak. Depending on the nature of the leak, it may or may not be worth fixing - so keep this in mind if you get a heap checker error in addition to assertion errors.

To provide a custom failure message, simply stream it into the macro using the << operator, or a sequence of such operators. An example:

Anything that can be streamed to an ostream can be streamed to an assertion macro--in particular, C strings and string objects. If a wide string (wchar_t*, TCHAR* in UNICODE mode on Windows, or std::wstring) is streamed to an assertion, it will be translated to UTF-8 when printed.

Fatal assertion Nonfatal assertion Verifies
ASSERT_TRUE(condition); EXPECT_TRUE(condition); condition is true
ASSERT_FALSE(condition); EXPECT_FALSE(condition); condition is false

Remember, when they fail, ASSERT_* yields a fatal failure and returns from the current function, while EXPECT_* yields a nonfatal failure, allowing the function to continue running. In either case, an assertion failure means its containing test fails.

Fatal assertion Nonfatal assertion Verifies
ASSERT_EQ(expected, actual);EXPECT_EQ(expected, actual); expected == actual
ASSERT_NE(val1, val2); EXPECT_NE(val1, val2); val1 != val2
ASSERT_LT(val1, val2); EXPECT_LT(val1, val2); val1 < val2
ASSERT_LE(val1, val2); EXPECT_LE(val1, val2); val1 <= val2
ASSERT_GT(val1, val2); EXPECT_GT(val1, val2); val1 > val2
ASSERT_GE(val1, val2); EXPECT_GE(val1, val2); val1 >= val2

Arguments are always evaluated exactly once. Therefore, it's OK for the arguments to have side effects. However, as with any ordinary C/C++ function, the arguments' evaluation order is undefined (i.e. the compiler is free to choose any order) and your code should not depend on any particular argument evaluation order.

ASSERT_EQ() does pointer equality on pointers. If used on two C strings, it tests if they are in the same memory location, not if they have the same value. Therefore, if you want to compare C strings (e.g. const char*) by value, use ASSERT_STREQ() , which will be described later on. In particular, to assert that a C string is NULL, use ASSERT_STREQ(NULL, c_string) . However, to compare two string objects, you should use ASSERT_EQ.

Fatal assertion Nonfatal assertion Verifies
ASSERT_STREQ(expected_str, actual_str); EXPECT_STREQ(expected_str, actual_str); the two C strings have the same content
ASSERT_STRNE(str1, str2); EXPECT_STRNE(str1, str2); the two C strings have different content
ASSERT_STRCASEEQ(expected_str, actual_str); EXPECT_STRCASEEQ(expected_str, actual_str); the two C strings have the same content, ignoring case
ASSERT_STRCASENE(str1, str2); EXPECT_STRCASENE(str1, str2); the two C strings have different content, ignoring case

  1. .
  2. If needed, define subroutines for your tests to share.

When using a fixture, use TEST_F() instead of TEST() as it allows you to access objects and subroutines in the test fixture:

TEST_F(test_case_name, test_name) {
 
... test body ...
}

Like TEST(), the first argument is the test case name, but for TEST_F() this must be the name of the test fixture class. You've probably guessed: _F is for fixture.

Unfortunately, the C++ macro system does not allow us to create a single macro that can handle both types of tests. Using the wrong macro causes a compiler error.

Also, you must first define a test fixture class before using it in a TEST_F(), or you'll get the compiler error "`virtual outside class declaration`".

For each test defined with TEST_F(), Google Test will:

  1. Create a fresh test fixture at runtime
  2. Immediately initialize it via SetUp() ,
  3. Run the test
  4. Clean up by calling TearDown()
  5. Delete the test fixture. Note that different tests in the same test case have different test fixture objects, and Google Test always deletes a test fixture before it creates the next one. Google Test does not reuse the same test fixture for multiple tests. Any changes one test makes to the fixture do not affect other tests.

As an example, let's write tests for a FIFO queue class named Queue, which has the following interface:

template <typename E> // E is the element type.
class Queue {
 
public:
 
Queue();
 
void Enqueue(const E& element);
  E
* Dequeue(); // Returns NULL if the queue is empty.
  size_t size
() const;
 
...
};

First, define a fixture class. By convention, you should give it the name FooTest where Foo is the class being tested.

class QueueTest : public ::testing::Test {
 
protected:
 
virtual void SetUp() {
    q1_
.Enqueue(1);
    q2_
.Enqueue(2);
    q2_
.Enqueue(3);
 
}

 
// virtual void TearDown() {}

 
Queue<int> q0_;
 
Queue<int> q1_;
 
Queue<int> q2_;
};

In this case, TearDown() is not needed since we don't have to clean up after each test, other than what's already done by the destructor.

Now we'll write tests using TEST_F() and this fixture.

TEST_F(QueueTest, IsEmptyInitially) {
  EXPECT_EQ
(0, q0_.size());
}

TEST_F
(QueueTest, DequeueWorks) {
 
int* n = q0_.Dequeue();
  EXPECT_EQ
(NULL, n);

  n
= q1_.Dequeue();
  ASSERT_TRUE
(n != NULL);
  EXPECT_EQ
(1, *n);
  EXPECT_EQ
(0, q1_.size());
 
delete n;

  n
= q2_.Dequeue();
  ASSERT_TRUE
(n != NULL);
  EXPECT_EQ
(2, *n);
  EXPECT_EQ
(1, q2_.size());
 
delete n;
}

The above uses both ASSERT_* and EXPECT_* assertions. The rule of thumb is to use EXPECT_* when you want the test to continue to reveal more errors after the assertion failure, and use ASSERT_* when continuing after failure doesn't make sense. For example, the second assertion in the Dequeue test is ASSERT_TRUE(n != NULL), as we need to dereference the pointer n later, which would lead to a segfault when n is NULL.

When these tests run, the following happens:

  1. Google Test constructs a QueueTest object (let's call it t1 ).
  2. t1.SetUp() initializes t1 .
  3. The first test ( IsEmptyInitially ) runs on t1 .
  4. t1.TearDown() cleans up after the test finishes.
  5. t1 is destructed.
  6. The above steps are repeated on another QueueTest object, this time running the DequeueWorks test.

Availability: Linux, Windows, Mac.

Note: Google Test automatically saves all Google Test flags when a test object is constructed, and restores them when it is destructed.

. You must call this function before calling RUN_ALL_TESTS(), or the flags won't be properly initialized.

On Windows, InitGoogleTest() also works with wide strings, so it can be used in programs compiled in UNICODE mode as well.

But maybe you think that writing all those main() functions is too much work? We agree with you completely and that's why Google Test provides a basic implementation of main(). If it fits your needs, then just link your test with gtest_main library and you are good to go.

in Visual C++. When you define your tests, Google Test creates certain static objects to register them. These objects are not referenced from elsewhere but their constructors are still supposed to run. When Visual C++ linker sees that nothing in the library is referenced from other places it throws the library out. You have to reference your library with tests from your main program to keep the linker from discarding it. Here is how to do it. Somewhere in your library code declare a function:

__declspec(dllimport) int PullInMyLibrary() { return 0; }

If you put your tests in a static library (not DLL) then __declspec(dllexport) is not required. Now, in your main program, write a code that invokes that function:

int PullInMyLibrary();
static int dummy = PullInMyLibrary();

This will keep your tests referenced and will make them register themselves at startup.

In addition, if you define your tests in a static library, add /OPT:NOREF to your main program linker options. If you use MSVC++ IDE, go to your .exe project properties/Configuration Properties/Linker/Optimization and set References setting to Keep Unreferenced Data (/OPT:NOREF). This will keep Visual C++ linker from discarding individual symbols generated by your tests from the final executable.

There is one more pitfall, though. If you use Google Test as a static library (that's how it is defined in gtest.vcproj) your tests must also reside in a static library. If you have to have them in a DLL, you must change Google Test to build into a DLL as well. Otherwise your tests will not run correctly or will not run at all. The general conclusion here is: make your life easier - do not write your tests in libraries!

, or continue with , which describes many more useful Google Test features.

Google Test is designed to be thread-safe. However, we haven't had time to implement the synchronization primitives on various platforms yet. Therefore, it is currently unsafe to use Google Test assertions from two threads concurrently. In most tests this is not an issue as usually the assertions are done in the main thread. If you want to help, you can volunteer to implement the necessary synchronization primitives in gtest-port.h.

阅读(2078) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~