summaryrefslogtreecommitdiff
path: root/src/mongo/unittest
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/unittest')
-rw-r--r--src/mongo/unittest/SConscript2
-rw-r--r--src/mongo/unittest/fixture_test.cpp88
-rw-r--r--src/mongo/unittest/unittest.cpp18
-rw-r--r--src/mongo/unittest/unittest.h39
4 files changed, 140 insertions, 7 deletions
diff --git a/src/mongo/unittest/SConscript b/src/mongo/unittest/SConscript
index 43eaf408862..12195e92fb4 100644
--- a/src/mongo/unittest/SConscript
+++ b/src/mongo/unittest/SConscript
@@ -12,4 +12,4 @@ env.StaticLibrary("unittest_crutch", ['crutch.cpp'])
env.CppUnitTest('unittest_test', 'unittest_test.cpp')
-
+env.CppUnitTest('fixture_test', 'fixture_test.cpp')
diff --git a/src/mongo/unittest/fixture_test.cpp b/src/mongo/unittest/fixture_test.cpp
new file mode 100644
index 00000000000..3a31dab3219
--- /dev/null
+++ b/src/mongo/unittest/fixture_test.cpp
@@ -0,0 +1,88 @@
+/**
+ * Copyright (C) 2012 10gen Inc.
+ */
+
+/**
+ * Unit tests of the unittest framework itself.
+ */
+
+#include "mongo/unittest/unittest.h"
+
+namespace {
+
+ class TestFixture : public mongo::unittest::Test {
+ protected:
+ int _myVar;
+ static int _num_set_ups;
+ static int _num_tear_downs;
+
+ void setUp() {
+ _num_set_ups++;
+ _myVar = 10;
+ }
+
+ void tearDown() {
+ _num_tear_downs++;
+ _myVar = 0;
+ }
+
+ int inc() {
+ return ++_myVar;
+ }
+
+ void throwSpecialException() {
+ throw FixtureExceptionForTesting();
+ }
+
+ };
+
+ int TestFixture::_num_set_ups = 0;
+ int TestFixture::_num_tear_downs = 0;
+
+ // NOTE:
+ // Test cases should not be designed that depend on the order they appear. But because
+ // we're testing the test framework itself, we do not follow this rule here and require the
+ // following four tests to be in that order.
+
+ // vvvvvvvvvvvvvvvvvvvvvvvv Do not add tests below
+
+ // This needs to be the very first test. Please, see NOTE above.
+ TEST_F(TestFixture, SetUpTest) {
+ ASSERT_EQUALS(_num_set_ups, 1);
+ ASSERT_EQUALS(_num_tear_downs, 0);
+ }
+
+ // This needs to be the second test. Please, see NOTE above.
+ TEST_F(TestFixture, TearDownTest) {
+ ASSERT_EQUALS(_num_set_ups, 2);
+ ASSERT_EQUALS(_num_tear_downs, 1);
+ }
+
+ // This needs to be the third/fourth test. Please, see NOTE above. We are
+ // finishing a test case by throwing an exception. Normally, the framework
+ // would treat this as an error. But what we'd like here is to make sure
+ // that the fixture tear down routines were called in that case.
+ TEST_F(TestFixture, Throwing) {
+ throwSpecialException();
+ }
+ TEST_F(TestFixture, TearDownAfterThrowing ) {
+ // Make sure tear down was called in the test above this.
+ ASSERT_EQUALS(_num_tear_downs, 3);
+ }
+
+ // ^^^^^^^^^^^^^^^^^^^^^^^^ Do not add test above
+
+ // New tests may be added below.
+
+ TEST_F(TestFixture, VariableAndMethodAccessTest) {
+ ASSERT_EQUALS(10, _myVar);
+ ASSERT_EQUALS(11, inc());
+ }
+
+ class EmptyFixture : public mongo::unittest::Test {
+ };
+
+ TEST_F(EmptyFixture, EmptyTest) {
+ }
+
+} // unnamed namespace
diff --git a/src/mongo/unittest/unittest.cpp b/src/mongo/unittest/unittest.cpp
index d67ad6ff6f3..44aaaabd5e6 100644
--- a/src/mongo/unittest/unittest.cpp
+++ b/src/mongo/unittest/unittest.cpp
@@ -78,7 +78,23 @@ namespace mongo {
void Test::run() {
setUp();
- _doTest();
+
+ // An uncaught exception does not prevent the tear down from running. But
+ // such an event still constitutes an error. To test this behavior we use a
+ // special exception here that when thrown does trigger the tear down but is
+ // not considered an error.
+ try {
+ _doTest();
+ }
+ catch (FixtureExceptionForTesting&) {
+ tearDown();
+ return;
+ }
+ catch (TestAssertionFailureException&) {
+ tearDown();
+ throw;
+ }
+
tearDown();
}
diff --git a/src/mongo/unittest/unittest.h b/src/mongo/unittest/unittest.h
index 67277c4cd87..f1556cf291b 100644
--- a/src/mongo/unittest/unittest.h
+++ b/src/mongo/unittest/unittest.h
@@ -110,6 +110,33 @@
void _TEST_TYPE_NAME(CASE_NAME, TEST_NAME)::_doTest()
/**
+ * Construct a single test named TEST_NAME that has access to a common class (a "fixture")
+ * named "FIXTURE_NAME".
+ *
+ * Usage:
+ *
+ * class FixtureClass : public mongo::unittest::Test {
+ * protected:
+ * int myVar;
+ * void setUp() { myVar = 10; }
+ * };
+ *
+ * TEST(FixtureClass, TestThatUsesFixture) {
+ * ASSERT_EQUALS(10, myVar);
+ * }
+ */
+#define TEST_F(FIXTURE_NAME, TEST_NAME) \
+ class _TEST_TYPE_NAME(FIXTURE_NAME, TEST_NAME) : public FIXTURE_NAME { \
+ private: \
+ virtual void _doTest(); \
+ \
+ static const RegistrationAgent<_TEST_TYPE_NAME(FIXTURE_NAME, TEST_NAME) > _agent; \
+ }; \
+ const ::mongo::unittest::Test::RegistrationAgent<_TEST_TYPE_NAME(FIXTURE_NAME, TEST_NAME) > \
+ _TEST_TYPE_NAME(FIXTURE_NAME, TEST_NAME)::_agent(#FIXTURE_NAME, #TEST_NAME); \
+ void _TEST_TYPE_NAME(FIXTURE_NAME, TEST_NAME)::_doTest()
+
+/**
* Macro to construct a type name for a test, from its "CASE_NAME" and "TEST_NAME".
* Do not use directly in test code.
*/
@@ -148,11 +175,6 @@ namespace mongo {
/**
* Base type for unit test fixtures. Also, the default fixture type used
* by the TEST() macro.
- *
- * TODO(schwerin): Implement a TEST_F macro that allows testers to specify
- * different subclasses of Test to be used as the test fixture. These subclasses
- * could then provide per-test set-up and tear-down code by overriding the
- * setUp and tearDown methods.
*/
class Test : private boost::noncopyable {
public:
@@ -171,6 +193,13 @@ namespace mongo {
RegistrationAgent(const std::string& suiteName, const std::string& testName);
};
+ /**
+ * This exception class is used to exercise the testing framework itself. If a test
+ * case throws it, the framework would not consider it an error.
+ */
+ class FixtureExceptionForTesting : public std::exception {
+ };
+
private:
/**
* Called on the test object before running the test.