Sunday, February 10, 2013

gtest setup

So, basically, to get gtest up and running, I follow the README instructions:

  • svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
  • cd !$
  • more README
  • I notice that some features require python, so I just ensure that I've got it:
    Jasons-MacBook-Air-2:make jason$ python --version
    Python 2.7.2
    
  • So now I go to this section:
    Setting up the Build
    --------------------
    
    To build Google Test and your tests that use it, you need to tell your build system where to find its headers and source files.  The exact way to do it depends on which build system you use, and is usually straightforward.
    
  • export GTEST_DIR=$(pwd)
  • Jasons-MacBook-Air-2:gtest-svn jason$ g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -c ${GTEST_DIR}/src/gtest-all.cc
    
    Jasons-MacBook-Air-2:gtest-svn jason$ ar -rv libgtest.a gtest-all.o
    ar: creating archive libgtest.a
    a - gtest-all.o
    
    Jasons-MacBook-Air-2:gtest-svn jason$ ls -lash libgtest*
    1848 -rw-r--r--  1 jason  staff   924K Feb  9 17:08 libgtest.a
    
  • Notice that the hello world recipe works:
    Jasons-MacBook-Air-2:make jason$ cd $GTEST_DIR/make
    Jasons-MacBook-Air-2:make jason$ make
    c++ -I../include -g -Wall -Wextra -c ../samples/sample1.cc
    c++ -I../include -g -Wall -Wextra -c ../samples/sample1_unittest.cc
    c++ -I../include -I.. -g -Wall -Wextra -c \
                ../src/gtest-all.cc
    In file included from ../src/gtest-all.cc:42:
    ../src/gtest.cc:364:12: warning: missing field 'owner_' initializer [-Wmissing-field-initializers]
    GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
               ^
    ../include/gtest/internal/gtest-port.h:1381:79: note: expanded from macro 'GTEST_DEFINE_STATIC_MUTEX_'
        ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false }
                                                                                  ^
    1 warning generated.
    c++ -I../include -I.. -g -Wall -Wextra -c \
                ../src/gtest_main.cc
    ar rv gtest_main.a gtest-all.o gtest_main.o
    ar: creating archive gtest_main.a
    a - gtest-all.o
    a - gtest_main.o
    c++ -I../include -g -Wall -Wextra -lpthread sample1.o sample1_unittest.o gtest_main.a -o sample1_unittest
    
    Jasons-MacBook-Air-2:make jason$ ./sample1_unittest 
    Running main() from gtest_main.cc
    [==========] Running 6 tests from 2 test cases.
    [----------] Global test environment set-up.
    [----------] 3 tests from FactorialTest
    [ RUN      ] FactorialTest.Negative
    [       OK ] FactorialTest.Negative (0 ms)
    [ RUN      ] FactorialTest.Zero
    [       OK ] FactorialTest.Zero (0 ms)
    [ RUN      ] FactorialTest.Positive
    [       OK ] FactorialTest.Positive (0 ms)
    [----------] 3 tests from FactorialTest (1 ms total)
    
    [----------] 3 tests from IsPrimeTest
    [ RUN      ] IsPrimeTest.Negative
    [       OK ] IsPrimeTest.Negative (0 ms)
    [ RUN      ] IsPrimeTest.Trivial
    [       OK ] IsPrimeTest.Trivial (0 ms)
    [ RUN      ] IsPrimeTest.Positive
    [       OK ] IsPrimeTest.Positive (0 ms)
    [----------] 3 tests from IsPrimeTest (0 ms total)
    
    [----------] Global test environment tear-down
    [==========] 6 tests from 2 test cases ran. (1 ms total)
    [  PASSED  ] 6 tests.
    
  • So, we reverse engineer what just happened for our purposes:
    /*
      A header file about squirrels and such...
    */
    #ifndef SQUIRREL_
    #define SQUIRREL_
    
    #include 
    
    using namespace std;
    
    // Returns a friendly greeting
    string hello(string whom);
    
    // A nut-collecting animal
    string varmint();
    
    #endif // SQUIRREL_
    
  • And, of course, a unit test...
    /*
            A unit test for squirrel functionality.
    */
    
    // need header files for SUT AND the test harness
    #include "squirrel.h"
    #include "gtest/gtest.h"
    #include 
    
    //using namespace std;
    
    // Tests varmint()
    TEST(SquirrelTest, Varmint){
      EXPECT_EQ( "squirrel", varmint() );
    }
    
    // Tests hello()
    TEST(SquirrelTest, Hello){
      EXPECT_EQ( "hello, squirrel!", hello(varmint()) );
      EXPECT_EQ( "hello, world!", hello("world") );
    }
    
  • And the implementation...
    /*
            squirrel.cc : an implementation
    */
    #ifndef SQUIRREL_
    #define SQUIRREL_
    
    #include "squirrel.h"
    #include 
    
    std::string hello(std::string whom){
      return "hello, " + whom + "!";
    }
    
    std::string varmint(){
      return "squirrel";
    }
    
    #endif
    
  • All held together by a build file:
    #!/bin/bash
    # compile my file
    g++ -I. -c squirrel.cc
    
    # and the main gtest file and my unit test file
    g++ -I. -I${GTEST_DIR}/include -c ${GTEST_DIR}/src/gtest_main.cc
    g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -I. -c squirrel_unittest.cc
    
    # link into a libtest.a propertyar -rv libtest.a ${GTEST_DIR}gtest-all.o gtest_main.o squirrel.o               
    g++ -I${GTEST_DIR} -I${GTEST_DIR}include -g -Wall -Wextra -lpthread libtest.a squirrel.o squirrel_unittest.o -o squirrel_unittest               
    ./squirrel_unittest
    
  • Voila!
    Jasons-MacBook-Air-2:squirrel jason$ ./trybuild 
    r - /Users/jason/src/gtest-svn/gtest-all.o
    r - gtest_main.o
    r - squirrel.o
    Running main() from gtest_main.cc
    [==========] Running 2 tests from 1 test case.
    [----------] Global test environment set-up.
    [----------] 2 tests from SquirrelTest
    [ RUN      ] SquirrelTest.Varmint
    [       OK ] SquirrelTest.Varmint (0 ms)
    [ RUN      ] SquirrelTest.Hello
    [       OK ] SquirrelTest.Hello (0 ms)
    [----------] 2 tests from SquirrelTest (0 ms total)
    
    [----------] Global test environment tear-down
    [==========] 2 tests from 1 test case ran. (0 ms total)
    [  PASSED  ] 2 tests.
    Jasons-MacBook-Air-2:squirrel jason$ 
    

So, at this point, we feel pretty pleased with ourselves, knowing that we've successfully TDD'd a simple bit of c++ functionality from the ground up. Next up is to get the whole mess into a quickly reproducible Xcode and github enabled setup...

No comments:

Post a Comment