15
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ROSAdvent Calendar 2016

Day 7

catkin_make run_tests と catkin_make test の違い

Last updated at Posted at 2016-12-06

はじめに

ROSコードのユニットテストの枠組みとして,rostestと言うものがあります.

詳細はROS Wiki - rostestあたりを覗くとなんとなく分かった気になれます.

このrostestの実行方法が2つあることに疑問を感じ,調べたことを共有することとします.

rostestの2つの実行方法とは?

下記2つのコマンドを指します.

  • catkin_make run_tests
  • catkin_make test

出力されるログが異なるのですが,どっちでもテストはできちゃいます.

ドキュメントにはなんて書いてある?

ROS Wiki - rostestを見てみると,catkinのタブを選択するとrun testsの説明が出てきて,rosbuildのタブを選択するとtestの説明が出てきます.

「ビルドシステムでコマンドが違うだけ,ちゃんちゃん」という話なら良かったのですが,いかんせんcatkinでもcatkin_make testが出来てしまいます.エイリアスとして残してくれているとかそういう位置づけなのかもしれませんが,じゃあ何が違うのかが余計気になってきます.

と思って調べてみても,これら2つのコマンドの違いをまとめた記述が全然出てこない笑.

結局,利用者側から見たrun_teststestの違いは?

色々試したところ,各々下記のような特長があることが分かりました.

catkin_make runtests

Pros

  • cppのテスト(gtest)を使う場合,テストコードを初回ビルドするのにこちらが必須.
  • テストノードが非同期でどんどん実行されるのでテスト実行時間自体は短い.
  • 詳細なエラーログを吐く上,テスト別の実行もできるので,デバッグ時はこちら便利.
    • run_tests_ でTabを押すと補完候補が出るので,特定のテストノードの実行が可能.

Cons

  • テストがたくさんある場合,どのテストがFailしたのかがパッと見てわかりづらい.
  • 常に0(success)を返すので,これrun_tests単体ではテストがFailしたかを判別できない.
    • 判定にはcatkin_test_resultsというコマンドを使う.直前のテストで1つでもFailがあれば0ではない値を返す.

catkin_make test

Pros

  • テスト全体の視認性が非常に良い.
  • 一度ビルドしたあとなら,普段使いのチェック用にするのが良さげ.
  • こちらでエラーを吐いたテストは,catkin_make run_tests側で詳細にデバッグ.
  • 直前のテストで1つでもFailがあれば0ではない値を返すので,test単体でテストと判定が可能.

Cons

  • cppのテスト(gtest)を使う場合,こちらではビルドしない.
    • 必ず catkin_make runtests のあとに,catkin_make testを行う必要がある.
  • Fail時にログを出してくれない.ただFailしたとしか言ってくれない.
  • シーケンシャルに実行するのでテスト実行時間が長い.

どう使い分けるか?

というわけで,私は勝手に下記のように使い分けることにしています.

  • 初回はビルドのため必ずcatkin_make run_testsを実行する.
    • でもどれがFailしたのか良くわからない.困った.
  • そこで,ビルドが終わったのを確認して別のターミナルでcatkin_make testFailするテストを確認する.
    • でも,Failの理由は分からない.困った.
  • そこで,Failしたテストを確認したら,catkin_make run_tests_hogehogeで,特定のテストだけ実行して詳細なデバッグログを確認する.

これにて一応一見落着.何か,行ったり来たりで,本当にこれで正しいのかがよく分かりません ^^;

上記仕様を手軽に確かめる方法

参考リポジトリ

下記リポジトリがシンプルととても分かり易いです.

ディレクトリ構成

テスト部分だけ抜粋したディレクトリ構成です.

ros-travis-integration/
│
└ ros_pkg_with_tests/
     │
     ├ scripts/
     │     │
     │     ├ test/
     │     │     │
     │     │     └ test_double.py
     │     │          ↑ python用 テストコード.
     │     └ double.py
     │          ↑ python コード実体.
     ├ src/
     │     │
     │     ├ test/
     │     │     │
     │     │     └ test_square.cpp
     │     │          ↑ cpp用 テストコード.
     │     ├ square.cpp
     │     │     ↕ cpp コード実体
     │     └ square.h
     │
     ├ package.xml
     │
     └ CMakeLists.txt

挙動の確認

今回はこのコードの中身は追わず,単にrun_teststestの挙動を確認することとします.

<your_ws>/src/に,上記リポジトリをクローンしておきます.

$ cd <your_ws>
$ catkin_make
$ source devel/setup.bash

テストコードビルド前にcatkin_make testを試す

一回,testを試してみます.ビルドされていないテストコードは実行できないはずです.

$ cd <your_ws>
$ catkin_make test
Base path: /<your_ws>
Source space: /<your_ws>/src
Build space: /<your_ws>/build
Devel space: /<your_ws>/devel
Install space: /<your_ws>/install
####
#### Running command: "make cmake_check_build_system" in "/<your_ws>/build"
####
####
#### Running command: "make test -j8 -l8" in "/<your_ws>/build"
####
Running tests...
Test project /<your_ws>/build
    Start 1: _ctest_ros_pkg_with_tests_gtest_ros_pkg_with_tests-test
1/2 Test #1: _ctest_ros_pkg_with_tests_gtest_ros_pkg_with_tests-test ...***Failed    0.05 sec
    Start 2: _ctest_ros_pkg_with_tests_nosetests_scripts.test
2/2 Test #2: _ctest_ros_pkg_with_tests_nosetests_scripts.test ..........   Passed    0.47 sec

50% tests passed, 1 tests failed out of 2

Total Test time (real) =   0.53 sec

The following tests FAILED:
	  1 - _ctest_ros_pkg_with_tests_gtest_ros_pkg_with_tests-test (Failed)
Errors while running CTest
make: *** [test] エラー 8

catkin_make run_testsを試す

$ cd <your_ws>
$ catkin_make run_tests
Base path: /<your_ws>
Source space: /<your_ws>/src
Build space: /<your_ws>/build
Devel space: /<your_ws>/devel
Install space: /<your_ws>/install
####
#### Running command: "make cmake_check_build_system" in "/<your_ws>/build"
####
####
#### Running command: "make run_tests -j8 -l8" in "/<your_ws>/build"
####
Scanning dependencies of target clean_test_results_ros_pkg_with_tests
Scanning dependencies of target gtest
[ 25%] Built target square
[ 50%] Removing test result files from '/<your_ws>/build/test_results/ros_pkg_with_tests'
- removing '/<your_ws>/build/test_results/ros_pkg_with_tests/MISSING-gtest-ros_pkg_with_tests-test.xml'
- removing '/<your_ws>/build/test_results/ros_pkg_with_tests/nosetests-scripts.test.xml'
Building CXX object gtest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
[ 50%] Built target clean_test_results_ros_pkg_with_tests
Linking CXX shared library libgtest.so
[ 50%] Built target gtest
Scanning dependencies of target gtest_main
[ 75%] Building CXX object gtest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
Linking CXX shared library libgtest_main.so
[ 75%] Built target gtest_main
Scanning dependencies of target ros_pkg_with_tests-test
[100%] Building CXX object ros-travis-integration/ros_pkg_with_tests/CMakeFiles/ros_pkg_with_tests-test.dir/src/test/test_square.cpp.o
Linking CXX executable /<your_ws>/devel/lib/ros_pkg_with_tests/ros_pkg_with_tests-test
[100%] Built target ros_pkg_with_tests-test
Scanning dependencies of target tests
[100%] Built target tests
Scanning dependencies of target _run_tests_ros_pkg_with_tests_nosetests_scripts.test
Scanning dependencies of target _run_tests_ros_pkg_with_tests_gtest_ros_pkg_with_tests-test
-- run_tests.py: execute commands
-- run_tests.py: execute commands
  /usr/bin/cmake -E make_directory /<your_ws>/build/test_results/ros_pkg_with_tests
  /<your_ws>/devel/lib/ros_pkg_with_tests/ros_pkg_with_tests-test --gtest_output=xml:/<your_ws>/build/test_results/ros_pkg_with_tests/gtest-ros_pkg_with_tests-test.xml
  /usr/bin/nosetests-2.7 -P --process-timeout=60 --where=/<your_ws>/src/ros-travis-integration/ros_pkg_with_tests/scripts/test --with-xunit --xunit-file=/<your_ws>/build/test_results/ros_pkg_with_tests/nosetests-scripts.test.xml
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestSuite
[ RUN      ] TestSuite.squareTwo
[       OK ] TestSuite.squareTwo (0 ms)
[ RUN      ] TestSuite.squareFour
[       OK ] TestSuite.squareFour (0 ms)
[----------] 2 tests from TestSuite (0 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (0 ms total)
[  PASSED  ] 2 tests.
-- run_tests.py: verify result "/<your_ws>/build/test_results/ros_pkg_with_tests/gtest-ros_pkg_with_tests-test.xml"
[100%] Built target _run_tests_ros_pkg_with_tests_gtest_ros_pkg_with_tests-test
Scanning dependencies of target _run_tests_ros_pkg_with_tests_gtest
[100%] Built target _run_tests_ros_pkg_with_tests_gtest
....
----------------------------------------------------------------------
Ran 4 tests in 0.001s

OK
-- run_tests.py: verify result "/<your_ws>/build/test_results/ros_pkg_with_tests/nosetests-scripts.test.xml"
[100%] Built target _run_tests_ros_pkg_with_tests_nosetests_scripts.test
Scanning dependencies of target _run_tests_ros_pkg_with_tests_nosetests
[100%] Built target _run_tests_ros_pkg_with_tests_nosetests
Scanning dependencies of target _run_tests_ros_pkg_with_tests
[100%] Built target _run_tests_ros_pkg_with_tests
Scanning dependencies of target run_tests
[100%] Built target run_tests

ビルドがされています.
ログが詳細なのは良いのですが,少しごちゃごちゃしています ^^;

このサンプルではテストの数が少ないのでまだいいほうですが,テスト数がウン10個とかになると,もはやパット見ただけではわけが分からなくなります笑.こっちとしては,まずは単純にテストが通ったかどうかだけを知りたいのです.

またcatkin_make testを試す

というわけで,晴れてビルドされたコードでこちらを試してみます.

$ cd <your_ws>
$ catkin_make test
Base path: /<your_ws>
Source space: /<your_ws>/src
Build space: /<your_ws>/build
Devel space: /<your_ws>/devel
Install space: /<your_ws>/install
####
#### Running command: "make cmake_check_build_system" in "/<your_ws>/build"
####
####
#### Running command: "make test -j8 -l8" in "/<your_ws>/build"
####
Running tests...
Test project /<your_ws>/build
    Start 1: _ctest_ros_pkg_with_tests_gtest_ros_pkg_with_tests-test
1/2 Test #1: _ctest_ros_pkg_with_tests_gtest_ros_pkg_with_tests-test ...   Passed    0.04 sec
    Start 2: _ctest_ros_pkg_with_tests_nosetests_scripts.test
2/2 Test #2: _ctest_ros_pkg_with_tests_nosetests_scripts.test ..........   Passed    0.34 sec

100% tests passed, 0 tests failed out of 2

Total Test time (real) =   0.39 sec

なんと分かりやすいこと!

catkin_make run_tests_ros_pkg_with_tests_nosetests_scripts.testを試す

仮に_ctest_ros_pkg_with_tests_nosetests_scripts.testFailしたとして,このテストだけを実行してみます.

$ cd <your_ws>
$ catkin_make run_tests_ros_pkg_with_tests_nosetests_scripts.test
Base path: /<your_ws>
Source space: /<your_ws>/src
Build space: /<your_ws>/build
Devel space: /<your_ws>/devel
Install space: /<your_ws>/install
####
#### Running command: "make cmake_check_build_system" in "/<your_ws>/build"
####
####
#### Running command: "make run_tests -j8 -l8" in "/<your_ws>/build"
####
Scanning dependencies of target run_tests_ros_pkg_with_tests_nosetests_scripts.test
-- run_tests.py: execute commands
  /usr/bin/cmake -E make_directory /<your_ws>/build/test_results/ros_pkg_with_tests
  /usr/bin/nosetests-2.7 -P --process-timeout=60 --where=/<your_ws>/src/ros-travis-integration/ros_pkg_with_tests/scripts/test --with-xunit --xunit-file=/<your_ws>/build/test_results/ros_pkg_with_tests/nosetests-scripts.test.xml
....
----------------------------------------------------------------------
Ran 4 tests in 0.001s

OK
-- run_tests.py: verify result "/<your_ws>/build/test_results/ros_pkg_with_tests/nosetests-scripts.test.xml"
Built target run_tests_ros_pkg_with_tests_nosetests_scripts.test

単一のテストコードのログだけなので,先ほどcatkin_make run_testsしたときよりはスッキリです.

なんとなく,提案した使い分けルールの雰囲気を感じてもらえたなら,幸いです.

おわりに

run_teststestの違いについてまとめてみました.

使い分けについては,一般的な方法かどうかは分からないので,悪しからず… ^^;
run_tests側のオプションでうまいことならないのかと感じているのですが,それっぽいオプションが見当たりませんでした….)

15
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?