C++ int Factorial(int n) { int result = 1; for (int i = 1; i <= n; i++) { result *= i; }
return result; }
以上是一个计算阶乘的函数,我们需要写测试代码验证它的正确性。
C++ #include "gtest/gtest.h"
// Tests factorial of negative numbers. TEST(FactorialTest, Negative) { // This test is named "Negative", and belongs to the "FactorialTest" // test case. EXPECT_EQ(1, Factorial(-5)); EXPECT_EQ(1, Factorial(-1)); EXPECT_GT(Factorial(-10), 0);
// // // EXPECT_EQ(expected, actual) is the same as // // EXPECT_TRUE((expected) == (actual)) // // except that it will print both the expected value and the actual // value when the assertion fails. This is very helpful for // debugging. Therefore in this case EXPECT_EQ is preferred. // // On the other hand, EXPECT_TRUE accepts any Boolean expression, // and is thus more general. // // }
C++ class FactorialTest_Zeor_Test : public Test { ...... private: void TestBody() override; static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; }
C++ UnitTest* UnitTest::GetInstance() { // CodeGear C++Builder insists on a public destructor for the // default implementation. Use this implementation to keep good OO // design with private destructor.
C++ 在 UnitTestImpl中定义了 test_suites_ // The vector of TestSuites in their original order. It owns the // elements in the vector. std::vector test_suites_;
在 TestSuite 中有一下定义了 test_info_list_ // The vector of TestInfos in their original order. It owns the // elements in the vector. std::vector test_info_list_;
在程序启动阶段,TEST定义的所有信息就会按照以上的形式保存到对应的vecotr中。
回看一下MakeAndRegisterTestInfo中的最后一个参数 new TestFactoryImpl。这里构建了一个TestFactoryImpl的模板对象:
C++ // Defines the abstract factory interface that creates instances // of a Test object. class TestFactoryBase { public: virtual ~TestFactoryBase() {}
// Creates a test instance to run. The instance is both created and destroyed // within TestInfoImpl::Run() virtual Test* CreateTest() = 0; TestFactoryBase() {}
private: TestFactoryBase(const TestFactoryBase&) = delete; TestFactoryBase& operator=(const TestFactoryBase&) = delete; }; // This class provides implementation of TestFactoryBase interface. // It is used in TEST and TEST_F macros. template class TestFactoryImpl : public TestFactoryBase { public: Test* CreateTest() override { return new TestClass; } };
C++ internal::TestFactoryBase* const factory_; // The factory that creates // the test object
通过以上的组织方式,不再需要使用者再写其它代码去运行测试用例。而由统一的main函数来完成:
C++ GTEST_API_ int main(int argc, char** argv) { // Since Google Mock depends on Google Test, InitGoogleMock() is // also responsible for initializing Google Test. Therefore there's // no need for calling testing::InitGoogleTest() separately. testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); }
Bash D:\code\googletest-main\out\build\x64-Debug\googletest>sample1_unittest.exe --gtest_filter=FactorialTest.* Running main() from D:\code\googletest-main\googletest\src\gtest_main.cc Note: Google Test filter = FactorialTest.* [==========] Running 3 tests from 1 test suite. [----------] Global test environment set-up. [----------] 3 tests from FactorialTest [ RUN ] FactorialTest.Negative [ OK ] FactorialTest.Negative (0 ms) [ RUN ] FactorialTest.Zero [ OK ] FactorialTest.Zero (0 ms) [ RUN ] FactorialTest.Positive [ OK ] FactorialTest.Positive (0 ms) [----------] 3 tests from FactorialTest (3 ms total)
[----------] Global test environment tear-down [==========] 3 tests from 1 test suite ran. (9 ms total) [ PASSED ] 3 tests.
可以修改一下,得到一些错误结果。
Bash D:\code\googletest-main\out\build\x64-Debug\googletest>sample1_unittest.exe --gtest_filter=FactorialTest.* Running main() from D:\code\googletest-main\googletest\src\gtest_main.cc Note: Google Test filter = FactorialTest.* [==========] Running 3 tests from 1 test suite. [----------] Global test environment set-up. [----------] 3 tests from FactorialTest [ RUN ] FactorialTest.Negative [ OK ] FactorialTest.Negative (0 ms) [ RUN ] FactorialTest.Zero D:\code\googletest-main\googletest\samples\sample1_unittest.cc(100): error: Expected equality of these values: 10 Factorial(0) Which is: 1 [ FAILED ] FactorialTest.Zero (0 ms) [ RUN ] FactorialTest.Positive D:\code\googletest-main\googletest\samples\sample1_unittest.cc(107): error: Expected equality of these values: 40310 Factorial(8) Which is: 40320 [ FAILED ] FactorialTest.Positive (0 ms) [----------] 3 tests from FactorialTest (1 ms total)
[----------] Global test environment tear-down [==========] 3 tests from 1 test suite ran. (5 ms total) [ PASSED ] 1 test. [ FAILED ] 2 tests, listed below: [ FAILED ] FactorialTest.Zero [ FAILED ] FactorialTest.Positive
C++ // Returns true if and only if n is a prime number. bool IsPrime(int n) { // Trivial case 1: small numbers if (n <= 1) return false;
// Trivial case 2: even numbers if (n % 2 == 0) return n == 2;
// Now, we have that n is odd and n >= 3.
// Try to divide n by every odd number i, starting from 3 for (int i = 3;; i += 2) { // We only have to try i up to the square root of n if (i > n / i) break;
// Now, we have i <= n/i < n. // If n is divisible by i, n is not prime. if (n % i == 0) return false; }
// n has no integer factor in the range (1, n), and thus is prime. return true; }
以上是一个检测是否输入是质数的函数。
C++ // Tests negative input. TEST(IsPrimeTest, Negative) { // This test belongs to the IsPrimeTest test case.
C++ TEST(MutuallyPrimeTest, positive) { int a = 4; int b = 10; EXPECT_TRUE(MutuallyPrime(a, b)); EXPECT_PRED2(MutuallyPrime, a, b); }
比如以上的输出是:
Bash [ RUN ] MutuallyPrimeTest.positive D:\code\googletest-main\googletest\samples\sample1_unittest.cc(158): error: Value of: MutuallyPrime(a, b) Actual: false Expected: true D:\code\googletest-main\googletest\samples\sample1_unittest.cc(159): error: MutuallyPrime(a, b) evaluates to false, where a evaluates to 4 b evaluates to 10 [ FAILED ] MutuallyPrimeTest.positive (0 ms)
使用EXPECT_PRED2可以打印出a,b的值。
EXPECT_PRED_FORMAT*
Fatal assertion
Nonfatal assertion
Verifies
ASSERT_PRED_FORMAT1(pred_formatter,val1)
EXPECT_PRED_FORMAT1(pred_formatter,val1)
Verifies that the predicate pred_formatter succeeds when passed the given values as arguments.
C++ // Returns the smallest prime common divisor of m and n, // or 1 when m and n are mutually prime. int SmallestPrimeCommonDivisor(int m, int n) { ... }
// Returns true if m and n have no common divisors except 1. bool MutuallyPrime(int m, int n) { ... }
测试代码:
C++ // A predicate-formatter for asserting that two integers are mutually prime. testing::AssertionResult AssertMutuallyPrime(const char* m_expr, const char* n_expr, int m, int n) { if (MutuallyPrime(m, n)) return testing::AssertionSuccess();
return testing::AssertionFailure() << m_expr << " and " << n_expr << " (" << m << " and " << n << ") are not mutually prime, " << "as they have a common divisor " << SmallestPrimeCommonDivisor(m, n); }
... const int a = 3; const int b = 4; const int c = 10; ... EXPECT_PRED_FORMAT2(AssertMutuallyPrime, a, b); // Succeeds EXPECT_PRED_FORMAT2(AssertMutuallyPrime, b, c); // Fails
C++ // Returns true if and only if n is a prime number. bool IsPrime(int n) { // Trivial case 1: small numbers if (n <= 1) return false;
// Trivial case 2: even numbers if (n % 2 == 0) return n == 2;
// Now, we have that n is odd and n >= 3.
// Try to divide n by every odd number i, starting from 3 for (int i = 3;; i += 2) { // We only have to try i up to the square root of n if (i > n / i) break;
// Now, we have i <= n/i < n. // If n is divisible by i, n is not prime. if (n % i == 0) return false; }
// n has no integer factor in the range (1, n), and thus is prime. return true; }
和
C++ bool IsPrimeFast(int n) { if (n <= 1) return false;
for (int i = 2; i * i <= n; i++) { // n is divisible by an integer other than 1 and itself. if ((n % i) == 0) return false; }
return true; }
都用来求质数。一套测试case应该可以满足两个函数,可以这样实现:
C++ class MyPrimeTest : public testing::TestWithParam> {
C++ using ::testing::Return; ... EXPECT_CALL(turtle, GetY()) .WillOnce(Return(100)) .WillOnce(Return(200)) .WillRepeatedly(Return(300));
通过Return,可以指定函数被调用后的返回值。
C++ using testing::ReturnPointee; ... int x = 0; MockFoo foo; EXPECT_CALL(foo, GetValue()) .WillRepeatedly(ReturnPointee(&x)); // Note the & here. x = 42; EXPECT_EQ(42, foo.GetValue()); // This will succeed now.
可以返回指针。
C++ using ::testing::ReturnRef;
class MockFoo : public Foo { ... MOCK_METHOD(Bar&, GetBar, (), (override)); MOCK_METHOD(const Bar&, GetBar, (), (const, override)); };
... MockFoo foo; Bar bar1, bar2; EXPECT_CALL(foo, GetBar()) // The non-const GetBar(). .WillOnce(ReturnRef(bar1)); EXPECT_CALL(Const(foo), GetBar()) // The const GetBar(). .WillOnce(ReturnRef(bar2));
可以返回引用。在不同的模式下,可以返回不同的值。
e. 可以设定期望的调用次序
C++ using ::testing::InSequence; ... TEST(FooTest, DrawsLineSegment) { ... { InSequence seq;