既存のコードの追加・改修の際に、動作を保証するテストコードがあり、自動テストできる環境があるのは重要で、Bitcoin Coreにももちろんテストコードと自動テストの仕組みがある。
Bitcoin Coreには単体テストと、リグレッション及びインテグレーションテスト用のテストコードがそれぞれ存在する。
- 単体テスト
https://github.com/bitcoin/bitcoin/blob/master/src/test/ 以下のC++で書かれたテストコード - リグレッション及びインテグレーションテスト
https://github.com/bitcoin/bitcoin/tree/master/test 以下のPythonで書かれたテストコード
単体テストの実行
テストコードはconfigureオプションで無効化していない限り、自動的にコンパイルされる。
実行対象のテストコードは、以下のMakefileに記載されている↓
- coreのテスト
https://github.com/bitcoin/bitcoin/blob/master/src/Makefile.test.include - qtのテスト
https://github.com/bitcoin/bitcoin/blob/master/src/Makefile.qttest.include
(他にもウォレットやsecp256k1などのテストが各フォルダにある。)
テストの実行は簡単で make check
を実行すればC++で書かれたテストが実行される。もしくは、コンパイルされたsrc/test/test_bitcoin
を実行してもいい。
$ ./src/test/test_bitcoin Running 258 test cases... *** No errors detected
bitcoin-qtの場合はsrc/qt/test/test_bitcoin-qt
を実行する。
個別のテストの実行
↑では全テストコードが実行されるので、個別に実行したい場合は、↓のように--run_test
オプションで対象のテストを指定して、src/test/test_bitcoin
を使って実行する。
$ ./src/test/test_bitcoin --run_test=script_tests --log_level=all
↑はsrc/test/script_tests.cpp のテスト実行。--log_level
オプションでログをコンソールに出力することもできる。
指定可能なオプションは--help
オプションを指定してtest_bitcoinを実行すれば確認できる。
テストコードの追加
単体テストのコードはboostのテストフレームワークを使って書かれてるので、テストコードを追加する際もそれを使用する。
既存のファイルにテストコードを追加する場合は、既存のテストファイルのBOOST_AUTO_TEST_CASE
関数内に追加するか、BOOST_AUTO_TEST_CASE
関数を追加して実装する。
新規にテストコードのファイルを追加する場合は、そのファイルを↑のMakefile.test.includeに追記する。
基本的にはソースファイルやクラス毎に1つテストファイルを作成することになっており、テストファイルの命名規則は<source_filename>_tests.cpp
。
(bitcoin-qtのテストはsrc/qt/test/
以下に追加)
リグレッション及びインテグレーションテストの実行
このテストは↓のセットで構成される。
- functional
RPCやP2Pインターフェースを介して動作するbitcoind及びbitcoin-qtの機能をテストするコード。 - util
Bitcoinのユーティリティのテストコードで、現在の対象はbitcoin-tx
のみ。
functionalテストの実行
各テストの実行は、それぞれpythonのテストファイルを直接実行すればいい。
$ test/functional/segwit.py 2017-08-10 06:51:43.129000 TestFramework (INFO): Initializing test directory /tmp/test92n84pq5 2017-08-10 06:51:45.901000 TestFramework (INFO): Verify sigops are counted in GBT with pre-BIP141 rules before the fork 2017-08-10 06:51:50.062000 TestFramework (INFO): Verify default node can't accept any witness format txs before fork ...
もしくは、test_runner.py
の引数に実行対象のテストファイルを指定する方法もある。
$ test/functional/test_runner.py segwit.py net.py Temporary test directory at /tmp/bitcoin_test_runner_20170810_155359 ............ net.py passed, Duration: 6 s .................................. segwit.py passed, Duration: 24 s TEST | STATUS | DURATION net.py | ✓ Passed | 6 s segwit.py | ✓ Passed | 24 s ALL | ✓ Passed | 30 s (accumulated) Runtime: 24 s
全テストケースを実行する場合は、テストファイルを指定せずに、test_runner.py
を実行する。
テストコードに記載されているログは、デフォルトではコンソールには出力されず全てtest_framework.log
というログファイルに記載され、テスト実行用の一時フォルダ内に格納される。
コンソールに出力する場合は-l
オプションを指定。
またPythonで書かれ、実行されているので、任意の場所に↓を入れて、デバッガをアタッチすることも可能。
import pdb; pdb.set_trace()
テストを追加する場合は、↓を参考にする。
https://github.com/bitcoin/bitcoin/blob/master/test/functional/README.md
utilテストの実行
↓のbitcoin-util-test.pyを実行する。-v
はverboseオプションで各テストのログが出力される。
$ test/util/bitcoin-util-test.py -v 2017-08-10 15:45:50,726 - INFO - PASSED: Creates a blank v1 transaction 2017-08-10 15:45:50,731 - INFO - PASSED: Creates a blank v1 transaction (output in json) 2017-08-10 15:45:50,735 - INFO - PASSED: Creates a blank transaction when nothing is piped into bitcoin-tx ...