1. 代码合集?
#include <gtest/gtest.h>
#include <stddef.h>
#include <algorithm>
#include <numeric>
#include <string>
#include <vector>
int Factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
// 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;
}
TEST(MyTest, math) {
printf("test math func\n");
EXPECT_EQ(true, IsPrime(79));
ASSERT_EQ(Factorial(5), 120);
}
// A simple string class.
class MyString {
private:
const char* c_string_;
const MyString& operator=(const MyString& rhs);
public:
// Clones a 0-terminated C string, allocating memory using new.
static const char* CloneCString(const char* a_c_string);
//
// C'tors
// The default c'tor constructs a NULL string.
MyString() : c_string_(nullptr) {}
// Constructs a MyString by cloning a 0-terminated C string.
explicit MyString(const char* a_c_string) : c_string_(nullptr) {
Set(a_c_string);
}
// Copy c'tor
MyString(const MyString& string) : c_string_(nullptr) {
Set(string.c_string_);
}
//
// D'tor. MyString is intended to be a final class, so the d'tor
// doesn't need to be virtual.
~MyString() { delete[] c_string_; }
// Gets the 0-terminated C string this MyString object represents.
const char* c_string() const { return c_string_; }
size_t Length() const { return c_string_ == nullptr ? 0 : strlen(c_string_); }
// Sets the 0-terminated C string this MyString object represents.
void Set(const char* c_string);
};
// Clones a 0-terminated C string, allocating memory using new.
const char* MyString::CloneCString(const char* a_c_string) {
if (a_c_string == nullptr) return nullptr;
const size_t len = strlen(a_c_string);
char* const clone = new char[len + 1];
memcpy(clone, a_c_string, len + 1);
return clone;
}
// Sets the 0-terminated C string this MyString object
// represents.
void MyString::Set(const char* a_c_string) {
// Makes sure this works when c_string == c_string_
const char* const temp = MyString::CloneCString(a_c_string);
delete[] c_string_;
c_string_ = temp;
}
// In this example, we test the MyString class (a simple string).
// Tests the default c'tor.
TEST(MyString, DefaultConstructor) {
const MyString s;
// Asserts that s.c_string() returns NULL.
//
// <TechnicalDetails>
//
// If we write NULL instead of
//
// static_cast<const char *>(NULL)
//
// in this assertion, it will generate a warning on gcc 3.4. The
// reason is that EXPECT_EQ needs to know the types of its
// arguments in order to print them when it fails. Since NULL is
// #defined as 0, the compiler will use the formatter function for
// int to print it. However, gcc thinks that NULL should be used as
// a pointer, not an int, and therefore complains.
//
// The root of the problem is C++'s lack of distinction between the
// integer number 0 and the null pointer constant. Unfortunately,
// we have to live with this fact.
//
// </TechnicalDetails>
EXPECT_STREQ(nullptr, s.c_string());
EXPECT_EQ(0u, s.Length());
}
const char kHelloString[] = "Hello, world!";
// Tests the c'tor that accepts a C string.
TEST(MyString, ConstructorFromCString) {
const MyString s(kHelloString);
EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
EXPECT_EQ(sizeof(kHelloString) / sizeof(kHelloString[0]) - 1, s.Length());
}
// Tests the copy c'tor.
TEST(MyString, CopyConstructor) {
const MyString s1(kHelloString);
const MyString s2 = s1;
EXPECT_EQ(0, strcmp(s2.c_string(), kHelloString));
}
// Tests the Set method.
TEST(MyString, Set) {
MyString s;
s.Set(kHelloString);
EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
// Set should work when the input pointer is the same as the one
// already in the MyString object.
s.Set(s.c_string());
EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
// Can we set the MyString to NULL?
s.Set(nullptr);
EXPECT_STREQ(nullptr, s.c_string());
}
// Queue is a simple queue implemented as a singled-linked list.
//
// The element type must support copy constructor.
template <typename E> // E is the element type
class Queue;
// QueueNode is a node in a Queue, which consists of an element of
// type E and a pointer to the next node.
template <typename E> // E is the element type
class QueueNode {
friend class Queue<E>;
public:
// Gets the element in this node.
const E& element() const { return element_; }
// Gets the next node in the queue.
QueueNode* next() { return next_; }
const QueueNode* next() const { return next_; }
private:
// Creates a node with a given element value. The next pointer is
// set to NULL.
explicit QueueNode(const E& an_element)
: element_(an_element), next_(nullptr) {}
// We disable the default assignment operator and copy c'tor.
const QueueNode& operator=(const QueueNode&);
QueueNode(const QueueNode&);
E element_;
QueueNode* next_;
};
template <typename E> // E is the element type.
class Queue {
public:
// Creates an empty queue.
Queue() : head_(nullptr), last_(nullptr), size_(0) {}
// D'tor. Clears the queue.
~Queue() { Clear(); }
// Clears the queue.
void Clear() {
if (size_ > 0) {
// 1. Deletes every node.
QueueNode<E>* node = head_;
QueueNode<E>* next = node->next();
for (;;) {
delete node;
node = next;
if (node == nullptr) break;
next = node->next();
}
// 2. Resets the member variables.
head_ = last_ = nullptr;
size_ = 0;
}
}
// Gets the number of elements.
size_t Size() const { return size_; }
// Gets the first element of the queue, or NULL if the queue is empty.
QueueNode<E>* Head() { return head_; }
const QueueNode<E>* Head() const { return head_; }
// Gets the last element of the queue, or NULL if the queue is empty.
QueueNode<E>* Last() { return last_; }
const QueueNode<E>* Last() const { return last_; }
// Adds an element to the end of the queue. A copy of the element is
// created using the copy constructor, and then stored in the queue.
// Changes made to the element in the queue doesn't affect the source
// object, and vice versa.
void Enqueue(const E& element) {
QueueNode<E>* new_node = new QueueNode<E>(element);
if (size_ == 0) {
head_ = last_ = new_node;
size_ = 1;
} else {
last_->next_ = new_node;
last_ = new_node;
size_++;
}
}
// Removes the head of the queue and returns it. Returns NULL if
// the queue is empty.
E* Dequeue() {
if (size_ == 0) {
return nullptr;
}
const QueueNode<E>* const old_head = head_;
head_ = head_->next_;
size_--;
if (size_ == 0) {
last_ = nullptr;
}
E* element = new E(old_head->element());
delete old_head;
return element;
}
// Applies a function/functor on each element of the queue, and
// returns the result in a new queue. The original queue is not
// affected.
template <typename F>
Queue* Map(F function) const {
Queue* new_queue = new Queue();
for (const QueueNode<E>* node = head_; node != nullptr;
node = node->next_) {
new_queue->Enqueue(function(node->element()));
}
return new_queue;
}
private:
QueueNode<E>* head_; // The first node of the queue.
QueueNode<E>* last_; // The last node of the queue.
size_t size_; // The number of elements in the queue.
// We disallow copying a queue.
Queue(const Queue&);
const Queue& operator=(const Queue&);
};
// To use a test fixture, derive a class from testing::Test.
class QueueTestSmpl3 : public testing::Test {
protected: // You should make the members protected s.t. they can be
// accessed from sub-classes.
// virtual void SetUp() will be called before each test is run. You
// should define it if you need to initialize the variables.
// Otherwise, this can be skipped.
void SetUp() override {
q1_.Enqueue(1);
q2_.Enqueue(2);
q2_.Enqueue(3);
}
// virtual void TearDown() will be called after each test is run.
// You should define it if there is cleanup work to do. Otherwise,
// you don't have to provide it.
//
// virtual void TearDown() {
// }
// A helper function that some test uses.
static int Double(int n) { return 2 * n; }
// A helper function for testing Queue::Map().
void MapTester(const Queue<int>* q) {
// Creates a new queue, where each element is twice as big as the
// corresponding one in q.
const Queue<int>* const new_q = q->Map(Double);
// Verifies that the new queue has the same size as q.
ASSERT_EQ(q->Size(), new_q->Size());
// Verifies the relationship between the elements of the two queues.
for (const QueueNode<int>*n1 = q->Head(), *n2 = new_q->Head();
n1 != nullptr; n1 = n1->next(), n2 = n2->next()) {
EXPECT_EQ(2 * n1->element(), n2->element());
}
delete new_q;
}
// Declares the variables your tests want to use.
Queue<int> q0_;
Queue<int> q1_;
Queue<int> q2_;
};
// When you have a test fixture, you define a test using TEST_F
// instead of TEST.
// Tests the default c'tor.
TEST_F(QueueTestSmpl3, DefaultConstructor) {
// You can access data in the test fixture here.
EXPECT_EQ(0u, q0_.Size());
}
// Tests Dequeue().
TEST_F(QueueTestSmpl3, Dequeue) {
int* n = q0_.Dequeue();
EXPECT_TRUE(n == nullptr);
n = q1_.Dequeue();
ASSERT_TRUE(n != nullptr);
EXPECT_EQ(1, *n);
EXPECT_EQ(0u, q1_.Size());
delete n;
n = q2_.Dequeue();
ASSERT_TRUE(n != nullptr);
EXPECT_EQ(2, *n);
EXPECT_EQ(1u, q2_.Size());
delete n;
}
// Tests the Queue::Map() function.
TEST_F(QueueTestSmpl3, Map) {
MapTester(&q0_);
MapTester(&q1_);
MapTester(&q2_);
}
// A simple monotonic counter.
class Counter {
private:
int counter_;
public:
// Creates a counter that starts at 0.
Counter() : counter_(0) {}
// Returns the current counter value, and increments it.
int Increment();
// Returns the current counter value, and decrements it.
int Decrement();
// Prints the current counter value to STDOUT.
void Print() const;
};
// Returns the current counter value, and increments it.
int Counter::Increment() { return counter_++; }
// Returns the current counter value, and decrements it.
// counter can not be less than 0, return 0 in this case
int Counter::Decrement() {
if (counter_ == 0) {
return counter_;
} else {
return counter_--;
}
}
// Prints the current counter value to STDOUT.
void Counter::Print() const { printf("%d", counter_); }
// Tests the Increment() method.
TEST(Counter, Increment) {
Counter c;
// Test that counter 0 returns 0
EXPECT_EQ(0, c.Decrement());
// EXPECT_EQ() evaluates its arguments exactly once, so they
// can have side effects.
EXPECT_EQ(0, c.Increment());
EXPECT_EQ(1, c.Increment());
EXPECT_EQ(2, c.Increment());
EXPECT_EQ(3, c.Decrement());
}
// 测试集为 MyTest,测试案例为 Sum
TEST(MyTest, Sum) {
printf("test sum func\n");
std::vector<int> vec{1, 2, 3, 4, 5};
int sum = std::accumulate(vec.begin(), vec.end(), 0);
EXPECT_EQ(sum, 15);
}
class QuickTest : public testing::Test {
protected:
// Remember that SetUp() is run immediately before a test starts.
// This is a good place to record the start time.
void SetUp() override { start_time_ = time(nullptr); }
// TearDown() is invoked immediately after a test finishes. Here we
// check if the test was too slow.
void TearDown() override {
// Gets the time when the test finishes
const time_t end_time = time(nullptr);
// Asserts that the test took no more than ~5 seconds. Did you
// know that you can use assertions in SetUp() and TearDown() as
// well?
EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";
}
// The UTC time (in seconds) when the test starts
time_t start_time_;
};
// We derive a fixture named IntegerFunctionTest from the QuickTest
// fixture. All tests using this fixture will be automatically
// required to be quick.
class IntegerFunctionTest : public QuickTest {
// We don't need any more logic than already in the QuickTest fixture.
// Therefore the body is empty.
};
// Now we can write tests in the IntegerFunctionTest test case.
// Tests Factorial()
TEST_F(IntegerFunctionTest, Factorial) {
// Tests factorial of negative numbers.
EXPECT_EQ(1, Factorial(-5));
EXPECT_EQ(1, Factorial(-1));
EXPECT_GT(Factorial(-10), 0);
// Tests factorial of 0.
EXPECT_EQ(1, Factorial(0));
// Tests factorial of positive numbers.
EXPECT_EQ(1, Factorial(1));
EXPECT_EQ(2, Factorial(2));
EXPECT_EQ(6, Factorial(3));
EXPECT_EQ(40320, Factorial(8));
}
// Tests IsPrime()
TEST_F(IntegerFunctionTest, IsPrime) {
// Tests negative input.
EXPECT_FALSE(IsPrime(-1));
EXPECT_FALSE(IsPrime(-2));
EXPECT_FALSE(IsPrime(INT_MIN));
// Tests some trivial cases.
EXPECT_FALSE(IsPrime(0));
EXPECT_FALSE(IsPrime(1));
EXPECT_TRUE(IsPrime(2));
EXPECT_TRUE(IsPrime(3));
// Tests positive input.
EXPECT_FALSE(IsPrime(4));
EXPECT_TRUE(IsPrime(5));
EXPECT_FALSE(IsPrime(6));
EXPECT_TRUE(IsPrime(23));
}
// The next test case (named "QueueTest") also needs to be quick, so
// we derive another fixture from QuickTest.
//
// The QueueTest test fixture has some logic and shared objects in
// addition to what's in QuickTest already. We define the additional
// stuff inside the body of the test fixture, as usual.
class QueueTest : public QuickTest {
protected:
void SetUp() override {
// First, we need to set up the super fixture (QuickTest).
QuickTest::SetUp();
// Second, some additional setup for this fixture.
q1_.Enqueue(1);
q2_.Enqueue(2);
q2_.Enqueue(3);
}
// By default, TearDown() inherits the behavior of
// QuickTest::TearDown(). As we have no additional cleaning work
// for QueueTest, we omit it here.
//
// virtual void TearDown() {
// QuickTest::TearDown();
// }
Queue<int> q0_;
Queue<int> q1_;
Queue<int> q2_;
};
// Now, let's write tests using the QueueTest fixture.
// Tests the default constructor.
TEST_F(QueueTest, DefaultConstructor) { EXPECT_EQ(0u, q0_.Size()); }
// Tests Dequeue().
TEST_F(QueueTest, Dequeue) {
int* n = q0_.Dequeue();
EXPECT_TRUE(n == nullptr);
n = q1_.Dequeue();
EXPECT_TRUE(n != nullptr);
EXPECT_EQ(1, *n);
EXPECT_EQ(0u, q1_.Size());
delete n;
n = q2_.Dequeue();
EXPECT_TRUE(n != nullptr);
EXPECT_EQ(2, *n);
EXPECT_EQ(1u, q2_.Size());
delete n;
}
TEST(MyTest, Compare) {
printf("test compare\n");
bool Compare = 100 > 0x63;
EXPECT_EQ(Compare, true);
}
TEST(MyTest, Add) {
printf("test add\n");
EXPECT_EQ(1 + 1, 2);
ASSERT_EQ(1 + 1, 2);
}
TEST(MyTest, Size) {
printf("test vec size\n");
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
EXPECT_EQ(2, vec.size());
}
class VectorTest : public testing::Test {
protected:
virtual void SetUp() override {
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
}
std::vector<int> vec;
};
// 注意这里使用 TEST_F,而不是 TEST
TEST_F(VectorTest, PushBack) {
// 虽然这里修改了 vec,但对其它测试函数来说是不可见的
printf("test vector\n");
vec.push_back(4);
EXPECT_EQ(vec.size(), 4);
EXPECT_EQ(vec.back(), 4);
}
TEST_F(VectorTest, Size) { EXPECT_EQ(vec.size(), 3); }
// The prime table interface.
class PrimeTable {
public:
virtual ~PrimeTable() {}
// Returns true if and only if n is a prime number.
virtual bool IsPrime(int n) const = 0;
// Returns the smallest prime number greater than p; or returns -1
// if the next prime is beyond the capacity of the table.
virtual int GetNextPrime(int p) const = 0;
};
// Implementation #1 calculates the primes on-the-fly.
class OnTheFlyPrimeTable : public PrimeTable {
public:
bool IsPrime(int n) const override {
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;
}
int GetNextPrime(int p) const override {
if (p < 0) return -1;
for (int n = p + 1;; n++) {
if (IsPrime(n)) return n;
}
}
};
// Implementation #2 pre-calculates the primes and stores the result
// in an array.
class PreCalculatedPrimeTable : public PrimeTable {
public:
// 'max' specifies the maximum number the prime table holds.
explicit PreCalculatedPrimeTable(int max)
: is_prime_size_(max + 1), is_prime_(new bool[max + 1]) {
CalculatePrimesUpTo(max);
}
~PreCalculatedPrimeTable() override { delete[] is_prime_; }
bool IsPrime(int n) const override {
return 0 <= n && n < is_prime_size_ && is_prime_[n];
}
int GetNextPrime(int p) const override {
for (int n = p + 1; n < is_prime_size_; n++) {
if (is_prime_[n]) return n;
}
return -1;
}
private:
void CalculatePrimesUpTo(int max) {
::std::fill(is_prime_, is_prime_ + is_prime_size_, true);
is_prime_[0] = is_prime_[1] = false;
// Checks every candidate for prime number (we know that 2 is the only even
// prime).
for (int i = 2; i * i <= max; i += i % 2 + 1) {
if (!is_prime_[i]) continue;
// Marks all multiples of i (except i itself) as non-prime.
// We are starting here from i-th multiplier, because all smaller
// complex numbers were already marked.
for (int j = i * i; j <= max; j += i) {
is_prime_[j] = false;
}
}
}
const int is_prime_size_;
bool* const is_prime_;
// Disables compiler warning "assignment operator could not be generated."
void operator=(const PreCalculatedPrimeTable& rhs);
};
// First, we define some factory functions for creating instances of
// the implementations. You may be able to skip this step if all your
// implementations can be constructed the same way.
template <class T>
PrimeTable* CreatePrimeTable();
template <>
PrimeTable* CreatePrimeTable<OnTheFlyPrimeTable>() {
return new OnTheFlyPrimeTable;
}
template <>
PrimeTable* CreatePrimeTable<PreCalculatedPrimeTable>() {
return new PreCalculatedPrimeTable(10000);
}
// Then we define a test fixture class template.
template <class T>
class PrimeTableTest : public testing::Test {
protected:
// The ctor calls the factory function to create a prime table
// implemented by T.
PrimeTableTest() : table_(CreatePrimeTable<T>()) {}
~PrimeTableTest() override { delete table_; }
// Note that we test an implementation via the base interface
// instead of the actual implementation class. This is important
// for keeping the tests close to the real world scenario, where the
// implementation is invoked via the base interface. It avoids
// got-yas where the implementation class has a method that shadows
// a method with the same name (but slightly different argument
// types) in the base interface, for example.
PrimeTable* const table_;
};
using testing::Types;
// Google Test offers two ways for reusing tests for different types.
// The first is called "typed tests". You should use it if you
// already know *all* the types you are gonna exercise when you write
// the tests.
// To write a typed test case, first use
//
// TYPED_TEST_SUITE(TestCaseName, TypeList);
//
// to declare it and specify the type parameters. As with TEST_F,
// TestCaseName must match the test fixture name.
// The list of types we want to test.
typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable> Implementations;
TYPED_TEST_SUITE(PrimeTableTest, Implementations);
// Then use TYPED_TEST(TestCaseName, TestName) to define a typed test,
// similar to TEST_F.
TYPED_TEST(PrimeTableTest, ReturnsFalseForNonPrimes) {
// Inside the test body, you can refer to the type parameter by
// TypeParam, and refer to the fixture class by TestFixture. We
// don't need them in this example.
// Since we are in the template world, C++ requires explicitly
// writing 'this->' when referring to members of the fixture class.
// This is something you have to learn to live with.
EXPECT_FALSE(this->table_->IsPrime(-5));
EXPECT_FALSE(this->table_->IsPrime(0));
EXPECT_FALSE(this->table_->IsPrime(1));
EXPECT_FALSE(this->table_->IsPrime(4));
EXPECT_FALSE(this->table_->IsPrime(6));
EXPECT_FALSE(this->table_->IsPrime(100));
}
TYPED_TEST(PrimeTableTest, ReturnsTrueForPrimes) {
EXPECT_TRUE(this->table_->IsPrime(2));
EXPECT_TRUE(this->table_->IsPrime(3));
EXPECT_TRUE(this->table_->IsPrime(5));
EXPECT_TRUE(this->table_->IsPrime(7));
EXPECT_TRUE(this->table_->IsPrime(11));
EXPECT_TRUE(this->table_->IsPrime(131));
}
TYPED_TEST(PrimeTableTest, CanGetNextPrime) {
EXPECT_EQ(2, this->table_->GetNextPrime(0));
EXPECT_EQ(3, this->table_->GetNextPrime(2));
EXPECT_EQ(5, this->table_->GetNextPrime(3));
EXPECT_EQ(7, this->table_->GetNextPrime(5));
EXPECT_EQ(11, this->table_->GetNextPrime(7));
EXPECT_EQ(131, this->table_->GetNextPrime(128));
}
// That's it! Google Test will repeat each TYPED_TEST for each type
// in the type list specified in TYPED_TEST_SUITE. Sit back and be
// happy that you don't have to define them multiple times.
using testing::Types;
// Sometimes, however, you don't yet know all the types that you want
// to test when you write the tests. For example, if you are the
// author of an interface and expect other people to implement it, you
// might want to write a set of tests to make sure each implementation
// conforms to some basic requirements, but you don't know what
// implementations will be written in the future.
//
// How can you write the tests without committing to the type
// parameters? That's what "type-parameterized tests" can do for you.
// It is a bit more involved than typed tests, but in return you get a
// test pattern that can be reused in many contexts, which is a big
// win. Here's how you do it:
// First, define a test fixture class template. Here we just reuse
// the PrimeTableTest fixture defined earlier:
template <class T>
class PrimeTableTest2 : public PrimeTableTest<T> {};
// Then, declare the test case. The argument is the name of the test
// fixture, and also the name of the test case (as usual). The _P
// suffix is for "parameterized" or "pattern".
TYPED_TEST_SUITE_P(PrimeTableTest2);
// Next, use TYPED_TEST_P(TestCaseName, TestName) to define a test,
// similar to what you do with TEST_F.
TYPED_TEST_P(PrimeTableTest2, ReturnsFalseForNonPrimes) {
EXPECT_FALSE(this->table_->IsPrime(-5));
EXPECT_FALSE(this->table_->IsPrime(0));
EXPECT_FALSE(this->table_->IsPrime(1));
EXPECT_FALSE(this->table_->IsPrime(4));
EXPECT_FALSE(this->table_->IsPrime(6));
EXPECT_FALSE(this->table_->IsPrime(100));
}
TYPED_TEST_P(PrimeTableTest2, ReturnsTrueForPrimes) {
EXPECT_TRUE(this->table_->IsPrime(2));
EXPECT_TRUE(this->table_->IsPrime(3));
EXPECT_TRUE(this->table_->IsPrime(5));
EXPECT_TRUE(this->table_->IsPrime(7));
EXPECT_TRUE(this->table_->IsPrime(11));
EXPECT_TRUE(this->table_->IsPrime(131));
}
TYPED_TEST_P(PrimeTableTest2, CanGetNextPrime) {
EXPECT_EQ(2, this->table_->GetNextPrime(0));
EXPECT_EQ(3, this->table_->GetNextPrime(2));
EXPECT_EQ(5, this->table_->GetNextPrime(3));
EXPECT_EQ(7, this->table_->GetNextPrime(5));
EXPECT_EQ(11, this->table_->GetNextPrime(7));
EXPECT_EQ(131, this->table_->GetNextPrime(128));
}
// Type-parameterized tests involve one extra step: you have to
// enumerate the tests you defined:
REGISTER_TYPED_TEST_SUITE_P(
PrimeTableTest2, // The first argument is the test case name.
// The rest of the arguments are the test names.
ReturnsFalseForNonPrimes, ReturnsTrueForPrimes, CanGetNextPrime);
// At this point the test pattern is done. However, you don't have
// any real test yet as you haven't said which types you want to run
// the tests with.
// To turn the abstract test pattern into real tests, you instantiate
// it with a list of types. Usually the test pattern will be defined
// in a .h file, and anyone can #include and instantiate it. You can
// even instantiate it more than once in the same program. To tell
// different instances apart, you give each of them a name, which will
// become part of the test case name and can be used in test filters.
// The list of types we want to test. Note that it doesn't have to be
// defined at the time we write the TYPED_TEST_P()s.
typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable>
PrimeTableImplementations;
INSTANTIATE_TYPED_TEST_SUITE_P(OnTheFlyAndPreCalculated, // Instance name
PrimeTableTest2, // Test case name
PrimeTableImplementations); // Type list
using ::testing::TestWithParam;
using ::testing::Values;
// As a general rule, to prevent a test from affecting the tests that come
// after it, you should create and destroy the tested objects for each test
// instead of reusing them. In this sample we will define a simple factory
// function for PrimeTable objects. We will instantiate objects in test's
// SetUp() method and delete them in TearDown() method.
typedef PrimeTable* CreatePrimeTableFunc();
PrimeTable* CreateOnTheFlyPrimeTable() { return new OnTheFlyPrimeTable(); }
template <size_t max_precalculated>
PrimeTable* CreatePreCalculatedPrimeTable() {
return new PreCalculatedPrimeTable(max_precalculated);
}
// Inside the test body, fixture constructor, SetUp(), and TearDown() you
// can refer to the test parameter by GetParam(). In this case, the test
// parameter is a factory function which we call in fixture's SetUp() to
// create and store an instance of PrimeTable.
class PrimeTableTestSmpl7 : public TestWithParam<CreatePrimeTableFunc*> {
public:
~PrimeTableTestSmpl7() override { delete table_; }
void SetUp() override { table_ = (*GetParam())(); }
void TearDown() override {
delete table_;
table_ = nullptr;
}
protected:
PrimeTable* table_;
};
TEST_P(PrimeTableTestSmpl7, ReturnsFalseForNonPrimes) {
EXPECT_FALSE(table_->IsPrime(-5));
EXPECT_FALSE(table_->IsPrime(0));
EXPECT_FALSE(table_->IsPrime(1));
EXPECT_FALSE(table_->IsPrime(4));
EXPECT_FALSE(table_->IsPrime(6));
EXPECT_FALSE(table_->IsPrime(100));
}
TEST_P(PrimeTableTestSmpl7, ReturnsTrueForPrimes) {
EXPECT_TRUE(table_->IsPrime(2));
EXPECT_TRUE(table_->IsPrime(3));
EXPECT_TRUE(table_->IsPrime(5));
EXPECT_TRUE(table_->IsPrime(7));
EXPECT_TRUE(table_->IsPrime(11));
EXPECT_TRUE(table_->IsPrime(131));
}
TEST_P(PrimeTableTestSmpl7, CanGetNextPrime) {
EXPECT_EQ(2, table_->GetNextPrime(0));
EXPECT_EQ(3, table_->GetNextPrime(2));
EXPECT_EQ(5, table_->GetNextPrime(3));
EXPECT_EQ(7, table_->GetNextPrime(5));
EXPECT_EQ(11, table_->GetNextPrime(7));
EXPECT_EQ(131, table_->GetNextPrime(128));
}
// In order to run value-parameterized tests, you need to instantiate them,
// or bind them to a list of values which will be used as test parameters.
// You can instantiate them in a different translation module, or even
// instantiate them several times.
//
// Here, we instantiate our tests with a list of two PrimeTable object
// factory functions:
INSTANTIATE_TEST_SUITE_P(OnTheFlyAndPreCalculated, PrimeTableTestSmpl7,
Values(&CreateOnTheFlyPrimeTable,
&CreatePreCalculatedPrimeTable<1000>));
// Suppose we want to introduce a new, improved implementation of PrimeTable
// which combines speed of PrecalcPrimeTable and versatility of
// OnTheFlyPrimeTable (see prime_tables.h). Inside it instantiates both
// PrecalcPrimeTable and OnTheFlyPrimeTable and uses the one that is more
// appropriate under the circumstances. But in low memory conditions, it can be
// told to instantiate without PrecalcPrimeTable instance at all and use only
// OnTheFlyPrimeTable.
class HybridPrimeTable : public PrimeTable {
public:
HybridPrimeTable(bool force_on_the_fly, int max_precalculated)
: on_the_fly_impl_(new OnTheFlyPrimeTable),
precalc_impl_(force_on_the_fly
? nullptr
: new PreCalculatedPrimeTable(max_precalculated)),
max_precalculated_(max_precalculated) {}
~HybridPrimeTable() override {
delete on_the_fly_impl_;
delete precalc_impl_;
}
bool IsPrime(int n) const override {
if (precalc_impl_ != nullptr && n < max_precalculated_)
return precalc_impl_->IsPrime(n);
else
return on_the_fly_impl_->IsPrime(n);
}
int GetNextPrime(int p) const override {
int next_prime = -1;
if (precalc_impl_ != nullptr && p < max_precalculated_)
next_prime = precalc_impl_->GetNextPrime(p);
return next_prime != -1 ? next_prime : on_the_fly_impl_->GetNextPrime(p);
}
private:
OnTheFlyPrimeTable* on_the_fly_impl_;
PreCalculatedPrimeTable* precalc_impl_;
int max_precalculated_;
};
using ::testing::Bool;
using ::testing::Combine;
using ::testing::TestWithParam;
using ::testing::Values;
namespace abc {
// To test all code paths for HybridPrimeTable we must test it with numbers
// both within and outside PreCalculatedPrimeTable's capacity and also with
// PreCalculatedPrimeTable disabled. We do this by defining fixture which will
// accept different combinations of parameters for instantiating a
// HybridPrimeTable instance.
class PrimeTableTest : public TestWithParam< ::std::tuple<bool, int> > {
protected:
void SetUp() override {
bool force_on_the_fly;
int max_precalculated;
std::tie(force_on_the_fly, max_precalculated) = GetParam();
table_ = new HybridPrimeTable(force_on_the_fly, max_precalculated);
}
void TearDown() override {
delete table_;
table_ = nullptr;
}
HybridPrimeTable* table_;
};
TEST_P(PrimeTableTest, ReturnsFalseForNonPrimes) {
// Inside the test body, you can refer to the test parameter by GetParam().
// In this case, the test parameter is a PrimeTable interface pointer which
// we can use directly.
// Please note that you can also save it in the fixture's SetUp() method
// or constructor and use saved copy in the tests.
EXPECT_FALSE(table_->IsPrime(-5));
EXPECT_FALSE(table_->IsPrime(0));
EXPECT_FALSE(table_->IsPrime(1));
EXPECT_FALSE(table_->IsPrime(4));
EXPECT_FALSE(table_->IsPrime(6));
EXPECT_FALSE(table_->IsPrime(100));
}
TEST_P(PrimeTableTest, ReturnsTrueForPrimes) {
EXPECT_TRUE(table_->IsPrime(2));
EXPECT_TRUE(table_->IsPrime(3));
EXPECT_TRUE(table_->IsPrime(5));
EXPECT_TRUE(table_->IsPrime(7));
EXPECT_TRUE(table_->IsPrime(11));
EXPECT_TRUE(table_->IsPrime(131));
}
TEST_P(PrimeTableTest, CanGetNextPrime) {
EXPECT_EQ(2, table_->GetNextPrime(0));
EXPECT_EQ(3, table_->GetNextPrime(2));
EXPECT_EQ(5, table_->GetNextPrime(3));
EXPECT_EQ(7, table_->GetNextPrime(5));
EXPECT_EQ(11, table_->GetNextPrime(7));
EXPECT_EQ(131, table_->GetNextPrime(128));
}
// In order to run value-parameterized tests, you need to instantiate them,
// or bind them to a list of values which will be used as test parameters.
// You can instantiate them in a different translation module, or even
// instantiate them several times.
//
// Here, we instantiate our tests with a list of parameters. We must combine
// all variations of the boolean flag suppressing PrecalcPrimeTable and some
// meaningful values for tests. We choose a small value (1), and a value that
// will put some of the tested numbers beyond the capability of the
// PrecalcPrimeTable instance and some inside it (10). Combine will produce
// all possible combinations.
INSTANTIATE_TEST_SUITE_P(MeaningfulTestParameters, PrimeTableTest,
Combine(Bool(), Values(1, 10)));
};
using ::testing::EmptyTestEventListener;
using ::testing::InitGoogleTest;
using ::testing::Test;
using ::testing::TestEventListeners;
using ::testing::TestInfo;
using ::testing::TestPartResult;
using ::testing::TestSuite;
using ::testing::UnitTest;
namespace {
// Provides alternative output mode which produces minimal amount of
// information about tests.
class TersePrinter : public EmptyTestEventListener {
private:
// Called before any test activity starts.
void OnTestProgramStart(const UnitTest& /* unit_test */) override {}
// Called after all test activities have ended.
void OnTestProgramEnd(const UnitTest& unit_test) override {
fprintf(stdout, "TEST %s\n", unit_test.Passed() ? "PASSED" : "FAILED");
fflush(stdout);
}
// Called before a test starts.
void OnTestStart(const TestInfo& test_info) override {
fprintf(stdout, "*** Test %s.%s starting.\n", test_info.test_suite_name(),
test_info.name());
fflush(stdout);
}
// Called after a failed assertion or a SUCCEED() invocation.
void OnTestPartResult(const TestPartResult& test_part_result) override {
fprintf(stdout, "%s in %s:%d\n%s\n",
test_part_result.failed() ? "*** Failure" : "Success",
test_part_result.file_name(), test_part_result.line_number(),
test_part_result.summary());
fflush(stdout);
}
// Called after a test ends.
void OnTestEnd(const TestInfo& test_info) override {
fprintf(stdout, "*** Test %s.%s ending.\n", test_info.test_suite_name(),
test_info.name());
fflush(stdout);
}
}; // class TersePrinter
TEST(CustomOutputTest, PrintsMessage) {
printf("Printing something from the test body...\n");
}
TEST(CustomOutputTest, Succeeds) {
SUCCEED() << "SUCCEED() has been invoked from here";
}
TEST(CustomOutputTest, Fails) {
EXPECT_EQ(1, 2)
<< "This test fails in order to demonstrate alternative failure messages";
}
} // namespace
using ::testing::EmptyTestEventListener;
using ::testing::InitGoogleTest;
using ::testing::Test;
using ::testing::TestEventListeners;
using ::testing::TestInfo;
using ::testing::TestPartResult;
using ::testing::UnitTest;
namespace {
// We will track memory used by this class.
class Water {
public:
// Normal Water declarations go here.
// operator new and operator delete help us control water allocation.
void* operator new(size_t allocation_size) {
allocated_++;
return malloc(allocation_size);
}
void operator delete(void* block, size_t /* allocation_size */) {
allocated_--;
free(block);
}
static int allocated() { return allocated_; }
private:
static int allocated_;
};
int Water::allocated_ = 0;
// This event listener monitors how many Water objects are created and
// destroyed by each test, and reports a failure if a test leaks some Water
// objects. It does this by comparing the number of live Water objects at
// the beginning of a test and at the end of a test.
class LeakChecker : public EmptyTestEventListener {
private:
// Called before a test starts.
void OnTestStart(const TestInfo& /* test_info */) override {
initially_allocated_ = Water::allocated();
}
// Called after a test ends.
void OnTestEnd(const TestInfo& /* test_info */) override {
int difference = Water::allocated() - initially_allocated_;
// You can generate a failure in any event handler except
// OnTestPartResult. Just use an appropriate Google Test assertion to do
// it.
EXPECT_LE(difference, 0) << "Leaked " << difference << " unit(s) of Water!";
}
int initially_allocated_;
};
TEST(ListenersTest, DoesNotLeak) {
Water* water = new Water;
delete water;
}
// This should fail when the --check_for_leaks command line flag is
// specified.
TEST(ListenersTest, LeaksWater) {
Water* water = new Water;
EXPECT_TRUE(water != nullptr);
}
} // namespace
int main(int argc, char *argv[]) {
::testing::InitGoogleTest(&argc, argv);
bool terse_output = false;
UnitTest& unit_test = *UnitTest::GetInstance();
// If we are given the --terse_output command line flag, suppresses the
// standard output and attaches own result printer.
if (terse_output) {
TestEventListeners& listeners = unit_test.listeners();
// Removes the default console output listener from the list so it will
// not receive events from Google Test and won't print any output. Since
// this operation transfers ownership of the listener to the caller we
// have to delete it as well.
delete listeners.Release(listeners.default_result_printer());
// Adds the custom output listener to the list. It will now receive
// events from Google Test and print the alternative output. We don't
// have to worry about deleting it since Google Test assumes ownership
// over it after adding it to the list.
listeners.Append(new TersePrinter);
}
int ret_val = RUN_ALL_TESTS();
// This is an example of using the UnitTest reflection API to inspect test
// results. Here we discount failures from the tests we expected to fail.
int unexpectedly_failed_tests = 0;
for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
const testing::TestSuite& test_suite = *unit_test.GetTestSuite(i);
for (int j = 0; j < test_suite.total_test_count(); ++j) {
const TestInfo& test_info = *test_suite.GetTestInfo(j);
// Counts failed tests that were not meant to fail (those without
// 'Fails' in the name).
if (test_info.result()->Failed() &&
strcmp(test_info.name(), "Fails") != 0) {
unexpectedly_failed_tests++;
}
}
}
// Test that were meant to fail should not affect the test program outcome.
if (unexpectedly_failed_tests == 0) ret_val = 0;
return ret_val;
}
2. 测试结果
?
|