Etikettarkiv: Testning

Testdriven utveckling: Del 2, En bra byggmiljö

För att fortsätta på ämnet testdriven utveckling tänkte jag gå ned på detaljerna, först kommer jag med lite tankar och tips på hut man skriver bra tester. Kanske det svåraste steget, speciellt svårt är det om man har mycket befintlig kod och få tester. Jag rekommenderar att man skriver testerna med i ett befintligt testharnesk. För att det går oftast snabbare och de finns mycket bra funktionalitet i dem. Skriver man kod i Java är JUnit det självklara valet, i Python, unittest. För C++ finns det lite mer variation, jag har länge jobbat med ccpunit. Men det är mycket jobba att komma igång med det systemet. Det är inflexibelt och inte mycket har uppdaterats på många år. Just nu är mitt favorit system Google Test.

Byggmiljö

Det första man måste göra för att kunna testa är att sätta upp en byggmiljö, jag kör min i Ubuntu 11.10 Oneiric, för C++ behöver jag en kompilator, make, jag vill ha cmake för att det blir så mycket enklare att bygga då. Jag vill alltid ha ett fungerade versions hanterings system så som git. Skall man bygga på ubuntu/debian måste man också se till att man har alla de -dev paket som behövs installerade. Saknar man dessa får man ofta spännande problem. Bygger man på MacOS behöver man bara installera git, cmake och xcode.

Projektet

Börja med att skapa en katalog för projektet, och initiera git för versions kontroll.

balp@silvara:~/localsrc$ mkdir tdd-blog
balp@silvara:~/localsrc$ cd tdd-blog/
balp@silvara:~/localsrc/tdd-blog$ git init
Initialized empty Git repository in /home/balp/localsrc/tdd-blog/.git/

Efter detta lägger vi till Google test som ett git subreposotory. Jag har skapar en mirror av googles svn för att kunna göra det här smidigt på github.com.

balp@silvara:~/localsrc/tdd-blog$ git submodule add git://github.com/balp/googletest.git googletest
Cloning into googletest...
remote: Counting objects: 3489, done.
remote: Compressing objects: 100% (583/583), done.
remote: Total 3489 (delta 2704), reused 3457 (delta 2672)
Receiving objects: 100% (3489/3489), 1.14 MiB | 463 KiB/s, done.
Resolving deltas: 100% (2704/2704), done.

Nu har vi alla grundkomponenter på plats och vi kan sätta igång. Det första vi skall göra när vi programmerar är att skapa en test som fallerar. Låt oss skapa en tom test fil, och editera vår byggfil.

balp@silvara:~/localsrc/tdd-blog$ touch tests.cpp
balp@silvara:~/localsrc/tdd-blog$ vim CMakeLists.txt

CMakeLists.txt behöver ett minimalt cmake projekt som bygger och kör testerna. Skriv in följande i filen.

cmake_minimum_required(VERSION 2.8)
project(BlogExamples)
enable_testing()

add_subdirectory(googletest)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/googletest/include)
add_executable(testprogram tests.cpp)
target_link_libraries(testprogram gtest_main )
add_test(NAME test COMMAND $<TARGET_FILE:testprogram> )

include(CTest)

Bygg och testa med den tomma test filen, jag brukar när jag jobbar från kommando raden sätta samman byggkommandona i ett subshell.

( rm -rf build/ ; mkdir build && cd build && cmake .. && make all test )

Fungerar detta som det skall så kommer man att se något i denna stil.

-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found PythonInterp: /usr/bin/python2.7
-- Looking for include files CMAKE_HAVE_PTHREAD_H
-- Looking for include files CMAKE_HAVE_PTHREAD_H - found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /home/balp/localsrc/tdd-blog/build
Scanning dependencies of target gtest
[ 33%] Building CXX object googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
Linking CXX static library libgtest.a
[ 33%] Built target gtest
Scanning dependencies of target gtest_main
[ 66%] Building CXX object googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
Linking CXX static library libgtest_main.a
[ 66%] Built target gtest_main
Scanning dependencies of target testprogram
[100%] Building CXX object CMakeFiles/testprogram.dir/tests.cpp.o
Linking CXX executable testprogram
[100%] Built target testprogram
UpdateCTestConfiguration from :/home/balp/localsrc/tdd-blog/build/DartConfiguration.tcl
Parse Config file:/home/balp/localsrc/tdd-blog/build/DartConfiguration.tcl
UpdateCTestConfiguration from :/home/balp/localsrc/tdd-blog/build/DartConfiguration.tcl
Parse Config file:/home/balp/localsrc/tdd-blog/build/DartConfiguration.tcl
Test project /home/balp/localsrc/tdd-blog/build
Constructing a list of tests
Done constructing a list of tests
Checking test dependency graph...
Checking test dependency graph end
test 1
 Start 1: test
1: Test command: /home/balp/localsrc/tdd-blog/build/testprogram
1: Test timeout computed to be: 1500
1: Running main() from gtest_main.cc
1: [==========] Running 0 tests from 0 test cases.
1: [==========] 0 tests from 0 test cases ran. (0 ms total)
1: [ PASSED ] 0 tests.
1/1 Test #1: test ............................. Passed 0.00 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.04 sec

Vi har nu ett bra startläge att börja skriva tester.