googletest 自动化测试例子合集

随笔2个月前发布 原来
36 0 0

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
");


  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
");


  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
");


  bool Compare = 100 > 0x63;


  EXPECT_EQ(Compare, true);


}


 


TEST(MyTest, Add) {


  printf("test add
");


  EXPECT_EQ(1 + 1, 2);


  ASSERT_EQ(1 + 1, 2);


}


 


TEST(MyTest, Size) {


  printf("test vec size
");


  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
");


  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
", 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.
", 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
%s
",


            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.
", test_info.test_suite_name(),


            test_info.name());


    fflush(stdout);


  }


};  // class TersePrinter


 


TEST(CustomOutputTest, PrintsMessage) {


  printf("Printing something from the test body...
");


}


 


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. 测试结果

googletest 自动化测试例子合集

 

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...