5

組み込みアプリケーションの新機能を開発しようとしていますが、テスト駆動型のアプローチを使用して開発したいと考えています。

このプロジェクトはピュア C で書かれており、IAR Embedded Workbench 6.60.1.5104 を使用して開発されています。Cortex-M3 デバイスである LPC1788 をターゲットにしており、すべての開発は 64 ビット Windows 7 マシンで行われています。現時点では、単体テストをターゲット ハードウェアではなく PC で実行することに賛成です (RAM はかなり限られています)。

私は組み込み C のテスト駆動開発と呼ばれる主題に関する有用な本に出くわし、Unity、CppUTest、Cedling などのツールについて教えてくれました。 ) 私のプロジェクトのために。ただし、Ceedling を現在の IAR ツールチェーンで動作するように構成するには、どのような手順を踏む必要があるのか​​正確にはわかりません。

Ceedling をインストールして「blinky」サンプル プロジェクトを作成し、IAR ツールチェーンを使用してビルドおよびテストしようとしています。iccarm.exeパスに追加し、blinky/project.yml以下のように編集しました。

---

# Notes:
# This is a fully tested project that demonstrates the use
# of a timer ISR to blink the on board LED of an Arduino UNO
:project:
  :use_exceptions: FALSE
  :use_test_preprocessor: TRUE
  :use_auxiliary_dependencies: TRUE
  :build_root: build
  :release_build: TRUE
  :test_file_prefix: test_

#You'll have to specify these
:environment:
  - :mcu: atmega328p
  - :f_cpu: 16000000UL 
  - :serial_port: COM8  #change this to the serial port you are using!!!
  - :objcopy: avr-objcopy
  # Uncomment these lines if you are using windows and don't have these tools in your path
  # - :path:
    # - C:\mingw\bin
    # - C:\WinAVR-20100110\bin
    # - C:\WinAVR-20100110\utils\bin
    # - #{ENV['PATH']}

:extension:
  :executable: .bin

:release_build:
  :output: blinky

:paths:
  :test:
    - +:test/**
    - -:test/support
  :source:
    - src/**
  :support:
    - test/support

:defines:
  # in order to add common defines:
  #  1) remove the trailing [] from the :common: section
  #  2) add entries to the :common: section (e.g. :test: has TEST defined)
  :commmon: &common_defines []
  :test:
    - *common_defines
    - TEST
  :test_preprocess:
    - *common_defines
    - TEST

:tools:
  :release_compiler:
    :executable: avr-gcc
    :arguments:
      - ${1}
      - -DTARGET
      - -DF_CPU=#{ENV['F_CPU']}
      - -mmcu=#{ENV['MCU']}
      - -Iinclude/
      - -Wall
      - -Os
      - -c
      - -o ${2}
  :release_linker:
    :executable: avr-gcc
    :arguments:
      - -mmcu=#{ENV['MCU']}
      - ${1}
      - -o ${2}.bin

:cmock:
  :mock_prefix: mock_
  :when_no_prototypes: :warn
  :enforce_strict_ordering: TRUE
  :plugins:
    - :ignore
  :treat_as:
    uint8:    HEX8
    uint16:   HEX16
    uint32:   UINT32
    int8:     INT8
    bool:     UINT8

:tools:
  :test_file_preprocessor:
    :executable: iccarm
    :name: 'IAR test file preprocessor'

  :test_includes_preprocessor:
    :executable: iccarm
    :name: 'IAR test includes preprocessor'

  :test_compiler:
    :executable: iccarm
    :name: 'IAR test compiler'

  :test_linker:
    :executable: iccarm
    :name: 'IAR test linker'

  :release_compiler:
    :executable: iccarm
    :name: 'IAR release compiler'

  :release_linker:
    :executable: iccarm
    :name: 'IAR release linker'

:plugins:
  :load_paths:
    - vendor/ceedling/plugins
  :enabled:
    - stdout_pretty_tests_report
    - module_generator
...

これとデフォルトの唯一の違いproject.ymlは、2 番目の:toolsセクションの内容です。

私は正しい方向に向かっていると思いiccarm.exeますが、ツールチェーンのこれらすべての部分に使用する正しい実行可能ファイルであるかどうか、およびどの引数を渡す必要があるかはわかりません。

IAR ツールチェーンを使用してブリンキー プロジェクトをビルドおよびテストするように Ceedling を構成できれば、実際のプロジェクトに同じ構成を適用できるはずです。ここで実行してみるとrake、次の出力が得られます。

$ rake


Test 'test_BlinkTask.c'
-----------------------
rake aborted!
Errno::ENOENT: No such file or directory @ rb_sysopen - build/test/preprocess/files/test_BlinkTask.c
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator_extractor.rb:18:in `readlines'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator_extractor.rb:18:in `extract_base_file_from_preprocessed_expansion'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator_file_handler.rb:14:in `preprocess_file'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator.rb:40:in `preprocess_file'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator.rb:12:in `block in setup'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator_helper.rb:33:in `preprocess_test_file'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/preprocessinator.rb:25:in `preprocess_test_and_invoke_test_mocks'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/test_invoker.rb:42:in `block in setup_and_invoke'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/test_invoker.rb:32:in `setup_and_invoke'
C:/Users/davidfallah/Documents/IAR Projects/blinky/vendor/ceedling/lib/ceedling/tasks_tests.rake:11:in `block (2 levels) in <top (required)>'
Tasks: TOP => default => test:all
(See full trace by running task with --trace)

--------------------
OVERALL TEST SUMMARY
--------------------

No tests executed.

これは、テスト ファイル プリプロセッサがbuild/test/preprocess/filesディレクトリの下にテスト ファイルをコピーする必要があるためだと思いますが、現在は発生していません。

少し調べてみたところ、参考になりそうなUnity の設定ファイルの例を見つけました。私が使用しているような IAR EW/Cortex M3 環境向けです。これにより、 Ceedling で指定する必要がある構成オプションが示される場合がありますproject.yml

Ceedling にblinkyIAR ツールチェーンを使用してプロジェクトをビルドおよびテストしてもらうことができれば、実際のプロジェクトで動作するように調整できることを願っています。どんな助けでも大歓迎です。

4

2 に答える 2

12

苦労しましたが、プロジェクトのテストに役立つように Ceedling を構成することができたと思います。これが、IAR プロジェクト内で Ceedling を使用しようとしている他の人にとって役立つことを願っています。

Ceedling CLI には、ceedling new <proj_name>Ceedling が期待する構造で新しいプロジェクトを作成できるコマンド ( ) があります。既存のプロジェクトの名前を指定することもできます。その場合、Ceedling 互換にするために必要なファイルのみが追加されます。これは、私のプロジェクトで行ったことです。

参考までに、このステップを実行した後、私のプロジェクト構造は次のようになりました。

.
├── build
│   ├── artifacts
│   │   └── test
│   ├── docs
│   ├── exe
│   ├── list
│   ├── logs
│   ├── obj
│   ├── temp
│   └── test
│       ├── cache
│       ├── dependencies
│       ├── list.i
│       ├── mocks
│       ├── out
│       ├── results
│       ├── runners
│       └── tests.map
├── project.yml
├── rakefile.rb
├── src
│   └── main
│       ├── c
│       │   ├── canDatabase.c
│       ├── include
│       │   ├── canDatabase.h
│       ├── python
│       └── resources
├── test
│   ├── support
│   └── test_canDatabase.c
├── <my_project>.dep
├── <my_project>.ewd
├── <my_project>.ewp
├── <my_project>.eww
├── vendor
│   └── ceedling
│       ├── docs
│       ├── lib
│       ├── plugins
│       └── vendor
└── version.properties

その後、@ user694733 が提案したように、IAR ツールのリファレンス マニュアルに目を通し、サンプル プロジェクトをビルドするときに IAR Embedded Workbench からの出力を調べました。project.ymlこの情報を使用して、以下のように編集しました。

:project:
  :use_exceptions: FALSE
  :use_test_preprocessor: FALSE
  :use_auxiliary_dependencies: TRUE
  :build_root: build
  :release_build: FALSE
  :test_file_prefix: test_

:environment:
  - :path:
    - 'C:\Program Files (x86)\IAR Systems\Embedded Workbench 6.5\arm\bin'
    - 'C:\Program Files (x86)\IAR Systems\Embedded Workbench 6.5\common\bin'
    - #{ENV['PATH']}

:extension:
  :executable: .out

:paths:
  :test:
    - +:test/**
    - -:test/support
  :source:
    - src/main/c/**
    - src/main/include/**
    - src/main/resources/**
  :support:
    - test/support

:defines:
  :commmon: &common_defines []
  :test:
    - *common_defines
    - TEST
  :test_preprocess:
    - *common_defines
    - TEST

:cmock:
  :mock_prefix: mock_
  :when_no_prototypes: :warn
  :enforce_strict_ordering: TRUE
  :plugins:
    - :ignore
    - :callback
  :treat_as:
    uint8:    HEX8
    uint16:   HEX16
    uint32:   UINT32
    int8:     INT8
    bool:     UINT8

:tools:
  :test_compiler:
    :executable: iccarm
    :name: 'IAR test compiler'
    :arguments:
      - -D _DLIB_FILE_DESCRIPTOR=1
      - --debug
      - --endian=little
      - --cpu=Cortex-M3
      - -e
      - --fpu=None
      - -Ol
      - --preprocess "build/test/list"
      - --dlib_config "C:/Program Files (x86)/IAR Systems/Embedded Workbench 6.5/arm/INC/c/DLib_Config_Normal.h"
      - -I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE
      - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR
      - -o "${2}"
      - --diag_suppress=Pa050
      - '"${1}"'

  :test_linker:
    :executable: ilinkarm
    :name: 'IAR test linker'
    :arguments:
      - --vfe
      - --redirect _Printf=_PrintfFull
      - --redirect _Scanf=_ScanfFull
      - --semihosting
      - --config "C:/Program Files (x86)/IAR Systems/Embedded Workbench 6.5/arm/config/generic_cortex.icf"
      - --map "build/test/tests.map"
      - -o "${2}"
      - '"${1}"'

  :test_fixture:
    :executable: cspybat
    :name: 'CSpyBat test runner'
    :arguments:
      - '"C:\Program Files (x86)\IAR Systems\Embedded Workbench 6.5\arm\bin\armproc.dll"'
      - '"C:\Program Files (x86)\IAR Systems\Embedded Workbench 6.5\arm\bin\armsim2.dll"'
      - '"${1}"'
      - --plugin "C:\Program Files (x86)\IAR Systems\Embedded Workbench 6.5\arm\bin\armbat.dll"
      - --backend -B
      - --endian=little
      - --cpu=Cortex-M3
      - --fpu=None
      - --semihosting

:plugins:
  :load_paths:
    - vendor/ceedling/plugins
  :enabled:
    - stdout_pretty_tests_report
    - module_generator
...

これは、Cortex-M3 デバイスで動作するように設計されたコードをテストするのに適した構成のようです。

rakefile.rbまた、テスト結果を一貫して印刷するために必要だったため、各テストの実行前に、生成されたテスト ファイルがクリーンアップされるように編集しました。

PROJECT_CEEDLING_ROOT = "vendor/ceedling"
load "#{PROJECT_CEEDLING_ROOT}/lib/ceedling.rb"

Ceedling.load_project

task :default => %w[ clean test:all ]

その後、単体テストを定義して実行することができました。以下は からの抜粋ですtest_canDatabase.c

#include "unity.h"
#include "canDatabase.h"

uint32_t actualId;
uint8_t actualPayload[8];
uint8_t actualPayloadLen;
uint8_t actualCanPort;

void mockHandler(uint32_t id, uint8_t payload[8], uint8_t payloadLen, uint8_t canPort)
{
  actualId = id;
  actualPayloadLen = payloadLen;
  actualCanPort = canPort;

  for (int i=0; i < payloadLen; i++)
  {
    actualPayload[i] = payload[i];
  }
}

void setUp(void)
{
  actualId = 0;
  actualPayloadLen = 0;
  actualCanPort = 0;

  for (int i=0; i < 8; i++)
  {
    actualPayload[i] = 0;
  }

  CANDB_Init(mockHandler);
}

void tearDown(void) {}

void test_Register_Tx_Definition()
{
  // GIVEN a CAN Tx message definition.
  CAN_TX_MESSAGE_DEFINITION_T definition;
  definition.id = 0;

  // WHEN we register the definition in the CAN database.
  int err = CANDB_RegisterTxDefinition(definition);

  // THEN the database should return SUCCESS (0x0).
  TEST_ASSERT_EQUAL_MESSAGE(0x0, err, "Registration should succeed");
}

void test_Register_Tx_Definition_Twice()
{
  // GIVEN a CAN Tx message definition.
  CAN_TX_MESSAGE_DEFINITION_T definition;
  definition.id = 0;

  // WHEN we register the definition once.
  CANDB_RegisterTxDefinition(definition);

  // AND we register the definition again.
  int err = CANDB_RegisterTxDefinition(definition);

  // THEN the database should return SUCCESS (0x0).
  TEST_ASSERT_EQUAL_MESSAGE(0x0, err, "Re-registration should succeed");
}

ターミナルから「ceedling」を呼び出すことで、自動テストを実行できるようになりました (プロジェクト ルートは現在の作業ディレクトリです)。

$ ceedling
---------------------
BUILD FAILURE SUMMARY
---------------------
Unit test failures.


Cleaning build artifacts...
(For large projects, this task may take a long time to complete)



Test 'test_canDatabase.c'
-------------------------
Generating runner for test_canDatabase.c...
Compiling test_canDatabase_runner.c...
Compiling test_canDatabase.c...
Compiling unity.c...
Compiling canDatabase.c...
Compiling cmock.c...
Linking test_canDatabase.out...
Running test_canDatabase.out...

-----------
TEST OUTPUT
-----------
[test_canDatabase.c]
  - ""
  - "     IAR C-SPY Command Line Utility V6.6.0.2752"
  - "     Copyright 2000-2013 IAR Systems AB."
  - ""
  - ""

-------------------
FAILED TEST SUMMARY
-------------------
[test_canDatabase.c]
  Test: test_Register_More_Than_Max_Allowed_Definitions
  At line (84): "Expected 1 Was 0. Registration > CANDB_MAX_TX_DEFINITIONS should fail"

  Test: test_Activate_Tx_Definition_With_Hardcoded_Payload
  At line (124): "Expected 0x00000001 Was 0x00000000. Incorrect ID"

--------------------
OVERALL TEST SUMMARY
--------------------
TESTED:  4
PASSED:  2
FAILED:  2
IGNORED: 0
于 2016-12-15T12:13:03.890 に答える