diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..15de58d --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,30 @@ +name: Test + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/cache@v4 + with: + path: | + ~/.cache/pip + ~/.platformio + key: ${{ runner.os }}-pio-${{ hashFiles('platformio.ini') }} + + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install PlatformIO + run: pip install platformio + + - name: Run tests + run: pio test -e test_native diff --git a/CLAUDE.md b/CLAUDE.md index f144324..a2aea37 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -82,10 +82,12 @@ pio run -e basic_m5stack_core2 -t upload # M5Stack書き込み ### テスト ```bash -cd test -make all_tests && ./all_tests # 全テスト実行 +pio test -e test_native # PlatformIOでテスト実行(推奨) +cd test && make test # Makefileでテスト実行(従来方式) ``` +GitHub Actions CI(`.github/workflows/test.yml`)で main への push / PR 時に自動テストが実行される。 + ※ローカル環境固有の設定(emsdkパスなど)は `CLAUDE.local.md` に記載 ## コード品質 diff --git a/platformio.ini b/platformio.ini index e997e3d..e080fb4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,24 +1,29 @@ -; fleximg Examples - Unified PlatformIO Configuration +; fleximg - PlatformIO Configuration ; -; Usage: -; Benchmark: -; pio run -e bench_native && .pio/build/bench_native/program -; pio run -e bench_m5stack_core2 -t upload +; src_dir はデフォルト (src/) を使用し、M5UnitUnified 方式で +; examples は build_src_filter で参照する構成。 ; -; Basic Demo: -; pio run -e basic_native && .pio/build/basic_native/program -; pio run -e basic_m5stack_core2 -t upload +; Test: +; pio test -e test_native ; -; Matte Demo: -; pio run -e matte_native && .pio/build/matte_native/program -; pio run -e matte_m5stack_core2 -t upload +; Benchmark: +; pio run -e bench_native && .pio/build/bench_native/program +; pio run -e bench_m5stack_core2 -t upload +; +; Basic Demo: +; pio run -e basic_native && .pio/build/basic_native/program +; pio run -e basic_m5stack_core2 -t upload +; +; Matte Demo: +; pio run -e matte_native && .pio/build/matte_native/program +; pio run -e matte_m5stack_core2 -t upload ; ; Serial monitor: pio device monitor -b 115200 [platformio] default_envs = bench_native -src_dir = examples -include_dir = src +; src_dir はデフォルト (src/) を使用 +; test_dir はデフォルト (test/) を使用 ; ============================================================================= ; Common Settings @@ -70,7 +75,6 @@ build_flags = -Wnull-dereference -Wunused -O0 -xc++ -std=c++17 - -I./src [common_native_sdl2] ; native + SDL2(macOSローカル環境用) @@ -88,12 +92,24 @@ build_flags = extends = common_native_sdl2 lib_deps = m5stack/M5Unified +; ============================================================================= +; Test Environment (Native) +; ============================================================================= +[env:test_native] +extends = common_native +test_framework = doctest +test_build_src = true +build_flags = + ${common_native.build_flags} + -Ithird_party/doctest +build_src_filter = -<*> + + ; ============================================================================= ; Benchmark Environments ; ============================================================================= [env:bench_native] extends = common_native -build_src_filter = + +build_src_filter = -<*> +<../examples/bench/src/*> build_flags = ${common_native.build_flags} -DBENCH_NATIVE=1 @@ -101,7 +117,7 @@ build_flags = [env:bench_m5stack_core2] extends = common_m5stack board = m5stack-core2 -build_src_filter = + +build_src_filter = -<*> +<../examples/bench/src/*> build_flags = ${common_m5stack.build_flags} -DBENCH_M5STACK=1 @@ -109,7 +125,7 @@ build_flags = [env:bench_m5stack_cores3] extends = common_m5stack board = m5stack-cores3 -build_src_filter = + +build_src_filter = -<*> +<../examples/bench/src/*> build_flags = ${common_m5stack.build_flags} -DBENCH_M5STACK=1 @@ -119,12 +135,12 @@ build_flags = ; ============================================================================= [env:basic_native] extends = common_native_m5 -build_src_filter = + +build_src_filter = -<*> +<../examples/m5stack_basic/src/*> [env:basic_m5stack_core2] extends = common_m5stack board = m5stack-core2 -build_src_filter = + +build_src_filter = -<*> +<../examples/m5stack_basic/src/*> build_flags = ${common_m5stack.build_flags} -DARDUINO_M5STACK_CORE2 @@ -132,7 +148,7 @@ build_flags = [env:basic_m5stack_cores3] extends = common_m5stack board = m5stack-cores3 -build_src_filter = + +build_src_filter = -<*> +<../examples/m5stack_basic/src/*> build_flags = ${common_m5stack.build_flags} -DARDUINO_M5STACK_CORES3 @@ -142,12 +158,12 @@ build_flags = ; ============================================================================= [env:matte_native] extends = common_native_m5 -build_src_filter = + +build_src_filter = -<*> +<../examples/m5stack_matte/src/*> [env:matte_m5stack_core2] extends = common_m5stack board = m5stack-core2 -build_src_filter = + +build_src_filter = -<*> +<../examples/m5stack_matte/src/*> build_flags = ${common_m5stack.build_flags} -DARDUINO_M5STACK_CORE2 @@ -155,7 +171,7 @@ build_flags = [env:matte_m5stack_cores3] extends = common_m5stack board = m5stack-cores3 -build_src_filter = + +build_src_filter = -<*> +<../examples/m5stack_matte/src/*> build_flags = ${common_m5stack.build_flags} -DARDUINO_M5STACK_CORES3 @@ -165,12 +181,12 @@ build_flags = ; ============================================================================= [env:hos_native] extends = common_native_m5 -build_src_filter = + +build_src_filter = -<*> +<../examples/m5stack_hos/src/*> [env:hos_m5stack_core2] extends = common_m5stack board = m5stack-core2 -build_src_filter = + +build_src_filter = -<*> +<../examples/m5stack_hos/src/*> build_flags = ${common_m5stack.build_flags} -DARDUINO_M5STACK_CORE2 @@ -178,7 +194,7 @@ build_flags = [env:hos_m5stack_cores3] extends = common_m5stack board = m5stack-cores3 -build_src_filter = + +build_src_filter = -<*> +<../examples/m5stack_hos/src/*> build_flags = ${common_m5stack.build_flags} -DARDUINO_M5STACK_CORES3 @@ -188,4 +204,4 @@ build_flags = ; ============================================================================= [env:vblur_test_native] extends = common_native -build_src_filter = + +build_src_filter = -<*> +<../examples/vblur_test/src/*> diff --git a/test/test_main.cpp b/test/test_main.cpp index 5dd18e7..45aff1a 100644 --- a/test/test_main.cpp +++ b/test/test_main.cpp @@ -3,3 +3,40 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include "doctest.h" + +// PlatformIO の DoctestTestCaseParser は === 区切りの verbose 出力を期待するが、 +// doctest のデフォルト出力にはこれが含まれない。 +// Listener を登録し、テストケース開始時に区切りブロックを出力することで +// PlatformIO 側で全テストケースが認識されるようにする。 +#ifdef PIO_UNIT_TESTING +#include + +struct PioListener : public doctest::IReporter { + PioListener(const doctest::ContextOptions&) {} + + void test_case_start(const doctest::TestCaseData& tc) override { + std::printf( + "=======================================================" + "================\n"); + std::printf("%s:%d:\n", tc.m_file.c_str(), tc.m_line); + if (tc.m_test_suite[0]) + std::printf("TEST SUITE: %s\n", tc.m_test_suite); + std::printf("TEST CASE: %s\n\n", tc.m_name); + } + + // 以下は空実装(Listener として必要なインターフェース) + void report_query(const doctest::QueryData&) override {} + void test_run_start() override {} + void test_run_end(const doctest::TestRunStats&) override {} + void test_case_reenter(const doctest::TestCaseData&) override {} + void test_case_end(const doctest::CurrentTestCaseStats&) override {} + void test_case_exception(const doctest::TestCaseException&) override {} + void subcase_start(const doctest::SubcaseSignature&) override {} + void subcase_end() override {} + void log_assert(const doctest::AssertData&) override {} + void log_message(const doctest::MessageData&) override {} + void test_case_skipped(const doctest::TestCaseData&) override {} +}; + +REGISTER_LISTENER("pio", 0, PioListener); +#endif