Ros Testing Tutorial

Post on 02-Jul-2015

437 views 1 download

description

A tutorial about Testing in ROS that I gave to the members of my lab. Code Examples and Exercises in: https://github.com/VGonPa/ros-testing-tutorial

Transcript of Ros Testing Tutorial

A Gentle Introduction to Gtest

Víctor González Pachecovictor.gonzalez.pacheco@gmail.com

March 2014

Test Driven Development in ROS

OutlineWhat to expectMotivationTesting LevelsWriting your first testsAdvice on making good testsResourcesExercise

Start with an example

Download material at:https://github.com/VGonPa/ros-testing-seminar

git clone https://github.com/VGonPa/ros-testing-seminar.git

What to expectfrom this seminar

What to expect

“Will I become a TDD master with this seminar?”

“Actually you might, eventually,if you start writing tests today!”

What to expect

You will learn where to start,the basics, and where to find more

information and help.

Motivation

Motivation

"Tests + Programming" is faster than just "Programming" [1]

MotivationSW Evolves

Requirements changeBug correctionsOptimizationsImprovements on design

How do you know if a change in your code didn’t break your previous work?

MotivationNOT testing is very dangerous:

“(Making large changes without tests) is like doing aerial gymnastics without a net.” [1]

The later you detect a bug, the more expensive is to fix it:

A bug detected in production may be REALLY expensiveLet alone if tomorrow you have a demo!

MotivationSome advantages of writing testsIt forces you to design better code

Faster incremental upgrades

A clear metric of your progress

It lets you refactor with greater confidence

Prevents recurring bugs

It enables you to blame others!

Other people can work with your code more easily

MotivationThe worst disadvantage

It will affect your thinking process......and your programming style.

But you will become a better programmer!

Motivation

“I don’t have time to write tests!”

Had you done the tests before, now you'd have time to do them!

More tests = less time debuggingMore tests = more time to program features

Test Driven Development (TTD)The process

Before programming, write tests

Write only the needed code to make the tests pass

Refactor to eliminate duplicated code, etc.

Repeat

Test Driven Development (TTD)

“Do I really need to write tests first?”

It’s much better to write them first,but if you don’t, be sure that your code is properly tested

Testing Levels

Imagine a simple scenario

N1 N2

Each node has its own code...

N1 N2

This is better...

N1 N2

There you have the first level

N1 N2

Library Unit Testing

Library Unit testing

N1

Library Unit Testing Test only your libraries

Code must be ROS Agnostic

GTest/Unittest(python)

Library Unit testing

N1Test each component separately

Library Unit Testing

N1

Test for:

common cases

extreme cases

Input errors

methods pre and post conditions

Now let’s test the node itself

N1 N2

Node LevelTesting

Node Level Unit testing

N1

Node LevelTesting

Test Node start/shutdown

Test Node external APIservices, published topics, subscribed topics (params?)

RosTest + GTest/Unittest

And, finally, the whole system

N1 N2

Integration/Regression Testing

Integration Testing

N1 N2

Test multiple nodes working as expected

RosTest + GTest/Unittest

Testing Levels: Overview

N1 N2

Library UnitTesting

Node LevelTesting

Integration/Regression Testing

Writing your first testsin ROS

Gtest and rostest

ROS provides two tools for executing tests:

gtest and rostest

GTestGoogle’s tool for unit testing

Regular cpp files

Executed with any of the following: ./my_test_file

make test # needs macro in CMakeLists.txt

rosmake <package_name> -t # needs macro in CMakeLists.txt

http://wiki.ros.org/gtest

Gtest and rostest

GTest

Gtest tutorials are quite good. We won’t cover them here.Read them if you don’t know how to write Gtests.

Gtest and rostest

Gtest and rostestrostest

roslaunch extension to launch tests

.launch syntax with added <test> tag

executed with any of the following: rostest <pgk_name> <test_name>.test

make test # needs macro in CMakeLists.txt

rosmake <package_name> -t # needs macro in CMakeLists.txt

http://wiki.ros.org/rostesthttp://wiki.ros.org/rostest/Writinghttp://wiki.ros.org/roslaunch/XML/test <------ <test> tag reference

Where should I use each one?

N1 N2

Node

Integration/Regression

Library

GtestRostest (+ Gtest)

Package structure with tests

my_ros_pkg/

CMakeLists.txt

bin/

build/

msg/

...

src/

test/ <--- gtests go here

test/ <--- rostests go here

InstallationGTestInstall: bash> sudo apt-get install libgtest-devIn your header files:

#include <gtest/gtest.h>

GMockInstall bash> sudo apt-get install google-mock

In your header files:#include <gmock/gmock.h>

Gtest CMakeLists.txt

# add gtest

rosbuild_add_gtest(test/my_test test/mytest.cpp

[other sources])# link required libraries

target_link_libraries(test/mytest linked_libraries)

rostest CMakeLists.txt

# add the test executable,

# keep it from being built by "make all"

rosbuild_add_executable(test_mynode EXCLUDE_FROM_ALL

src/test/test_mynode.cpp)

# Link test_mynode against gtest

# and add a dependency to the "test" target

rosbuild_add_gtest_build_flags(test_mynode)

# Make sure rostest launches test/mynode.test during "make test"

rosbuild_add_rostest(test/mynode.test)

Let’s see an example

Checkout the package rostest_node_example from the material

Some adviseHow to make good tests

What to testExample: max(list_of_ints)

Normal casesmax([10,3,0,-1,8])

Extreme casesmax([3,3,3,3,3,3])

max(2)

Error casesmax([‘aaa’,3,nan,None])

max([])

What not to testThe test itselfModules that cannot be broken (or that there is no solution):

System callsHardware failures

Modules from which your code depends on:Standard Libraries, modules written by others, etc.

They already have (or should have) their own tests

Exhaustive tests

Writing more “testable” codeSometimes it’s difficult to test a component in isolation

Dependencies between components

Some components might be on the network (eg. sockets)

Some components might needuser input

Some comopnents might just be slow to test

Writing more “testable” code

Solution: Break dependencies

Program against interfaces

Specify dependencies in the constructor

Use mocks in your tests

Common features of good testsA good test should be:

Independent1. You do not need to read other tests to understand what a test does2. If a test fails, it should be easy to find the bug3. Each test focuses on a single aspect

Repetible

Quick: Use mocks

Small: Enables you to easily spot bugs. Big tests functions have many parts affecting each other

Beware the Unit-Integration Chimera!

Unit TestingSweet spot

Integration TestingSweet spot

It will eat your productivity!

Bibliography and Resources

Bibliography and ResourcesB. Eckel, "Thinking in C++ Volume 2". (online version)

Google C++ Testing Framework projectProject: http://code.google.com/p/googletest/

Guía inicial: http://code.google.com/p/googletest/wiki/V1_6_Primer

Avanzado: http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide

Ejemplos: http://code.google.com/p/googletest/wiki/V1_6_Samples

Dependency injection, mocks: Google Mock: http://code.google.com/p/googlemock/

Bibliography and ResourcesROS Unit Testing: http://wiki.ros.org/UnitTesting

ROS GTest: http://wiki.ros.org/gtest

ROS rostest: http://wiki.ros.org/rostest

Bibliography and ResourcesThis seminar has been greatly inspired from this talk from Zhanyong Wan:

Effective C++ Testing Using Google Test

There you will find more information regarding Gtest and Unit testing in general

Questions?https://github.com/VGonPa/ros-testing-seminar

Excercise

1. Counter node’s counter should be initiated by parameter to any number

2. Factorial calculates factorial of counter3. Test the library, node and integration using gtest +

rostests

counter_node factorial_node

/counter /factorial/do_increment

This seminar is licensed under the Creative Commons license CC Attribution 4.0 International

You are free to use and adapt this presentation as long as you give credit to the author.More information can be found here:

http://creativecommons.org/licenses/by/4.0/