From 29d8235540f1983c3dbd53a23783530017be80e7 Mon Sep 17 00:00:00 2001 From: shiqian Date: Tue, 9 Sep 2008 03:01:38 +0000 Subject: Adds new files for type-parameterized tests, which I forgot to commit in the previous revision. --- samples/sample6_unittest.cc | 301 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 samples/sample6_unittest.cc (limited to 'samples/sample6_unittest.cc') diff --git a/samples/sample6_unittest.cc b/samples/sample6_unittest.cc new file mode 100644 index 00000000..dba52f0e --- /dev/null +++ b/samples/sample6_unittest.cc @@ -0,0 +1,301 @@ +// Copyright 2008 Google Inc. +// All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// This sample shows how to test common properties of multiple +// implementations of the same interface (aka interface tests). We +// put the code to be tested and the tests in the same file for +// simplicity. + +#include +#include + +// Section 1. the interface and its implementations. + +// The prime table interface. +class PrimeTable { + public: + virtual ~PrimeTable() {} + + // Returns true iff 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: + virtual bool IsPrime(int n) const { + 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; + } + + virtual int GetNextPrime(int p) const { + for (int n = p + 1; n > 0; n++) { + if (IsPrime(n)) return n; + } + + return -1; + } +}; + +// Implementation #2 pre-calculates the primes and stores the result +// in a vector. +class PreCalculatedPrimeTable : public PrimeTable { + public: + // 'max' specifies the maximum number the prime table holds. + explicit PreCalculatedPrimeTable(int max) : is_prime_(max + 1) { + CalculatePrimesUpTo(max); + } + + virtual bool IsPrime(int n) const { + return 0 <= n && n < is_prime_.size() && is_prime_[n]; + } + + virtual int GetNextPrime(int p) const { + for (int n = p + 1; n < is_prime_.size(); n++) { + if (is_prime_[n]) return n; + } + + return -1; + } + + private: + void CalculatePrimesUpTo(int max) { + fill(is_prime_.begin(), is_prime_.end(), true); + is_prime_[0] = is_prime_[1] = false; + + for (int i = 2; i <= max; i++) { + if (!is_prime_[i]) continue; + + // Marks all multiples of i (except i itself) as non-prime. + for (int j = 2*i; j <= max; j += i) { + is_prime_[j] = false; + } + } + } + + std::vector is_prime_; +}; + +// Sections 2. the tests. + +// 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 +PrimeTable* CreatePrimeTable(); + +template <> +PrimeTable* CreatePrimeTable() { + return new OnTheFlyPrimeTable; +} + +template <> +PrimeTable* CreatePrimeTable() { + return new PreCalculatedPrimeTable(10000); +} + +// Then we define a test fixture class template. +template +class PrimeTableTest : public testing::Test { + protected: + // The ctor calls the factory function to create a prime table + // implemented by T. + PrimeTableTest() : table_(CreatePrimeTable()) {} + + virtual ~PrimeTableTest() { 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; + +#ifdef GTEST_HAS_TYPED_TEST + +// 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_CASE(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 Implementations; + +TYPED_TEST_CASE(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_CASE. Sit back and be +// happy that you don't have to define them multiple times. + +#endif // GTEST_HAS_TYPED_TEST + +#ifdef GTEST_HAS_TYPED_TEST_P + +// 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 PrimeTableTest2 : public PrimeTableTest { +}; + +// 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_CASE_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_CASE_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 + PrimeTableImplementations; +INSTANTIATE_TYPED_TEST_CASE_P(OnTheFlyAndPreCalculated, // Instance name + PrimeTableTest2, // Test case name + PrimeTableImplementations); // Type list + +#endif // GTEST_HAS_TYPED_TEST_P -- cgit v1.2.3 From 3d7042176307f0d7700a3640f3b3bcc8790b8fcd Mon Sep 17 00:00:00 2001 From: vladlosev Date: Thu, 20 Nov 2008 01:40:35 +0000 Subject: Value-parameterized tests and many bugfixes --- samples/sample6_unittest.cc | 93 ++++----------------------------------------- 1 file changed, 8 insertions(+), 85 deletions(-) (limited to 'samples/sample6_unittest.cc') diff --git a/samples/sample6_unittest.cc b/samples/sample6_unittest.cc index dba52f0e..36166729 100644 --- a/samples/sample6_unittest.cc +++ b/samples/sample6_unittest.cc @@ -30,91 +30,12 @@ // Author: wan@google.com (Zhanyong Wan) // This sample shows how to test common properties of multiple -// implementations of the same interface (aka interface tests). We -// put the code to be tested and the tests in the same file for -// simplicity. +// implementations of the same interface (aka interface tests). -#include -#include - -// Section 1. the interface and its implementations. - -// The prime table interface. -class PrimeTable { - public: - virtual ~PrimeTable() {} - - // Returns true iff 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; -}; +// The interface and its implementations are in this header. +#include "prime_tables.h" -// Implementation #1 calculates the primes on-the-fly. -class OnTheFlyPrimeTable : public PrimeTable { - public: - virtual bool IsPrime(int n) const { - 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; - } - - virtual int GetNextPrime(int p) const { - for (int n = p + 1; n > 0; n++) { - if (IsPrime(n)) return n; - } - - return -1; - } -}; - -// Implementation #2 pre-calculates the primes and stores the result -// in a vector. -class PreCalculatedPrimeTable : public PrimeTable { - public: - // 'max' specifies the maximum number the prime table holds. - explicit PreCalculatedPrimeTable(int max) : is_prime_(max + 1) { - CalculatePrimesUpTo(max); - } - - virtual bool IsPrime(int n) const { - return 0 <= n && n < is_prime_.size() && is_prime_[n]; - } - - virtual int GetNextPrime(int p) const { - for (int n = p + 1; n < is_prime_.size(); n++) { - if (is_prime_[n]) return n; - } - - return -1; - } - - private: - void CalculatePrimesUpTo(int max) { - fill(is_prime_.begin(), is_prime_.end(), true); - is_prime_[0] = is_prime_[1] = false; - - for (int i = 2; i <= max; i++) { - if (!is_prime_[i]) continue; - - // Marks all multiples of i (except i itself) as non-prime. - for (int j = 2*i; j <= max; j += i) { - is_prime_[j] = false; - } - } - } - - std::vector is_prime_; -}; - -// Sections 2. the tests. +#include // First, we define some factory functions for creating instances of // the implementations. You may be able to skip this step if all your @@ -153,10 +74,10 @@ class PrimeTableTest : public testing::Test { PrimeTable* const table_; }; -using testing::Types; - #ifdef GTEST_HAS_TYPED_TEST +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 @@ -218,6 +139,8 @@ TYPED_TEST(PrimeTableTest, CanGetNextPrime) { #ifdef GTEST_HAS_TYPED_TEST_P +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 -- cgit v1.2.3 From 0af0709b02899f9177db55eba7929e65e5834b29 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Mon, 23 Feb 2009 23:21:55 +0000 Subject: Cleans up macro definitions. --- samples/sample6_unittest.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'samples/sample6_unittest.cc') diff --git a/samples/sample6_unittest.cc b/samples/sample6_unittest.cc index 36166729..dd0df31f 100644 --- a/samples/sample6_unittest.cc +++ b/samples/sample6_unittest.cc @@ -74,7 +74,7 @@ class PrimeTableTest : public testing::Test { PrimeTable* const table_; }; -#ifdef GTEST_HAS_TYPED_TEST +#if GTEST_HAS_TYPED_TEST using testing::Types; @@ -137,7 +137,7 @@ TYPED_TEST(PrimeTableTest, CanGetNextPrime) { #endif // GTEST_HAS_TYPED_TEST -#ifdef GTEST_HAS_TYPED_TEST_P +#if GTEST_HAS_TYPED_TEST_P using testing::Types; -- cgit v1.2.3 From dac3e879c56a50696a36f53e1e5e353e48fa665f Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Tue, 14 Sep 2010 05:35:59 +0000 Subject: Include gtest headers as user headers instead of system headers. --- samples/sample6_unittest.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'samples/sample6_unittest.cc') diff --git a/samples/sample6_unittest.cc b/samples/sample6_unittest.cc index dd0df31f..8f2036a5 100644 --- a/samples/sample6_unittest.cc +++ b/samples/sample6_unittest.cc @@ -35,7 +35,7 @@ // The interface and its implementations are in this header. #include "prime_tables.h" -#include +#include "gtest/gtest.h" // First, we define some factory functions for creating instances of // the implementations. You may be able to skip this step if all your -- cgit v1.2.3