Zephyrのテストフレームワーク調査③〜はじめてのZmock〜

はじめに

Zephyrにはテストフレームワーク (Mockもあります!) が用意されています。 テストは大事です。さっさとテストを作れるようにしましょう!

docs.zephyrproject.org

前回は、単純なテストを試したので、今回は、Mockを試してみます。

サンプル

とにかくサンプルを動かしてみます。

|> zephyr/tests/ztest/test/mock

$ mkdir build && cd $
$ cmake -GNinja -DBOARD=unit_testing ..
$ ninja run-test
Running test suite mock_framework_tests
===================================================================
starting test - test_parameter_tests
PASS - test_parameter_tests
===================================================================
starting test - test_return_value_tests
PASS - test_return_value_tests
===================================================================
starting test - test_multi_value_tests
PASS - test_multi_value_tests
===================================================================
Test suite mock_framework_tests succeeded
===================================================================
PROJECT EXECUTION SUCCESSFUL

そう言えば、BOARDがunit_testingかどうかでcmakeが分岐していました。 試しに、qemu_cortex_m3をターゲットにしてみます。

$ mkdir build && cd $
$ cmake -GNinja -DBOARD=qemu_cortex_m3 ..
...
This warning is for project developers.  Use -Wno-dev to suppress it.

CMake Warning at ../../../../CMakeLists.txt:1372 (message):
  

        ------------------------------------------------------------
        --- WARNING:  __ASSERT() statements are globally ENABLED ---
        --- The kernel will run more slowly and use more memory  ---
        ------------------------------------------------------------
...

なるほど。assertが有効になっているので遅いし、メモリを使う、という警告が出ます。

$ ninja run
[1/104] Preparing syscall dependency handling

[98/104] Linking C executable zephyr/zephyr_prebuilt.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:       12236 B       256 KB      4.67%
            SRAM:        4856 B        64 KB      7.41%
        IDT_LIST:           8 B         2 KB      0.39%
[103/104] To exit from QEMU enter: 'CTRL+a, x'[QEMU] CPU: cortex-m3
qemu-system-arm: warning: nic stellaris_enet.0 has no peer
***** Booting Zephyr OS 1.13.99 *****
Running test suite mock_framework_tests
===================================================================
starting test - test_parameter_tests
PASS - test_parameter_tests
===================================================================
starting test - test_return_value_tests
PASS - test_return_value_tests
===================================================================
starting test - test_multi_value_tests
PASS - test_multi_value_tests
===================================================================
Test suite mock_framework_tests succeeded
===================================================================
PROJECT EXECUTION SUCCESSFUL

unit_testingのときと違い、Zephyrがフルビルドされています。 いいですね。後で、実ボード上でも動くか試してみましょう。

CMakeLists.txt

普通のユニットテストと同じです。

cmake_minimum_required(VERSION 3.8.2)
if(BOARD STREQUAL unit_testing)
  list(APPEND SOURCES src/main.c)

  include($ENV{ZEPHYR_BASE}/tests/unit/unittest.cmake)
  project(mock)
else()
  include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
  project(mock)

  FILE(GLOB app_sources src/*.c)
  target_sources(app PRIVATE ${app_sources})
endif()

prj.conf

少し設定項目が増えます。

CONFIG_ZTEST=y
CONFIG_ZTEST_ASSERT_VERBOSE=1
CONFIG_ZTEST_MOCKING=y
CONFIG_ZTEST_PARAMETER_COUNT=5

CONFIG_ZTEST_MOCKINGは、Mockを有効にするために必要です。

CONFIG_ZTEST_PARAMETER_COUNTは、Mockで検証するパラメータおよび戻り値の数を制限します。デフォルトでは1のようです。

src/main.c

テストコードを書いていきます。

#include <ztest.h>

static int expect_two_parameters_and_return(int a, int b) {
    ztest_check_expected_value(a);
    ztest_check_expected_value(b);

    return ztest_get_return_value();
}

static void mock_test(void) {
    ztest_expect_value(expect_two_parameters_and_return, a, 1);
    ztest_expect_value(expect_two_parameters_and_return, b, 2);
    ztest_returns_value(expect_two_parameters_and_return, 3);

    zassert_equal(expect_two_parameters_and_return(1, 2), 3, NULL);
}

void test_main(void) {
    ztest_test_suite(my_first_mock,
        ztest_unit_test(mock_test)
    );

    ztest_run_test_suite(my_first_mock);
}

うわ、面倒くさいです…。

動作確認

無事動きます。

$ mkdir build && cd $_
$ cmake -GNinja -DBOARD=unit_testing ..
$ ninja run-test
Running test suite my_first_mock
===================================================================
starting test - mock_test
PASS - mock_test
===================================================================
Test suite my_first_mock succeeded
===================================================================
PROJECT EXECUTION SUCCESSFUL

感想

Mockの仕組みがあるだけでかなり嬉しいです。 が、ちょっと書き方が面倒ですね…。