can't go to sleep

組み込み開発の多くをRubyで自動化することに興味があります

UnityとCMock その2

さて、今回はCMockの導入の解説をします。

事前条件

まず、前回「UnityとCMock その1」で紹介した通りのフォルダ構成にしてください。
CMockのrakefileや、CMockのexamplesから作っても良いのですが、CMockの中のrakefileでは、specやシステムテストの構成なども含まれているようです。
そのため、CMock単体の理解には相応しくないと思うので、今回はUnityをベースに、Unity+CMockのみのシンプルな構成を構築します。

フォルダ構成

次に、mocksフォルダを作成してください。
次に、GitHubから取得したCMockのlibフォルダとconfigフォルダを、unityフォルダにコピーしてください。
次に、CMockのsrcフォルダの中にある2つのファイルを、unityのsrcフォルダにコピーしてください。
これで、ファイルの移動は完成です。

必要ファイルの編集

次に、gcc_32.ymlファイルを編集します。
ファイルの最後に以下の行を追加してください。

:cmock:
  :plugins:
    - :callback
    - :ignore
  :includes:
    - **.h
  :mock_path: 'mocks'

ここで、作成されるモックファイルの中でincludeさせたいファイルがある場合は、上記の**.hにヘッダファイル名を入れてください(とりあえず最初は空白でOK)。

また、compiler:のincludes:に、「- 'mocks/'」を追加してください。

compiler:
# pathやoptionsなど記載の下
  includes:
    prefix: '-I'
    items:
      - 'mocks/'
      - 'src/'

次に、rakefile_helper.rbファイルを編集します。
「# Detect dependencies and build required modules」と記載のある行(188行目あたり)

      extract_headers(test).each do |header|
        # Compile corresponding source file if it exists
        src_file = find_source_file(header, include_dirs)
        if !src_file.nil?
          obj_list << compile(src_file, test_defines)
        end
      end

      header_list = extract_headers(test) + ['cmock.h']
      header_list.each do |header|
      
        #create mocks if needed
        if (header =~ /Mock/) 
          require "lib/cmock.rb" 
          @cmock ||= CMock.new($cfg_file) 
          @cmock.setup_mocks([$cfg['compiler']['source_path']+header.gsub('Mock','')])
        end
        
      end

      #compile all mocks
      header_list.each do |header|
        #compile source file header if it exists
        src_file = find_source_file(header, include_dirs)
        if !src_file.nil?
          obj_list << compile(src_file, test_defines)
        end
      end

このように書き換えてください。
ちなみに、この内容はCMockのexamplesのrakefile_helper.rbの185行目当たりの(ほぼ)コピーになります。(require "lib/cmock.rb"のパスを変えています。)
ちなみに、その行は、

          require UNITY_ROOT+"/lib/cmock.rb" 

としてもいいかもしれません。

変更は以上になります。

動作確認

とりあえずMockのテストをしたい場合は、CMockのexamplesから、src内容をコピーして、unityのsrcフォルダに、test内容をコピーして、unityのtestフォルダに入れてから、rakeをしてみてください。
現状のままだと途中でこけてしまうので、gcc_32.ymlのcmockのincludesに、下記の通り-Types.hを追加してください。

:cmock:
  :plugins:
    - :callback
    - :ignore
  :includes:
    - Types.h

これでもいろいろとうまくいきませんが、とりあえずmocksフォルダにモックが作成されていることが確認できれば設定はOKだと思われます。
ちなみに、モックファイルの作成方法は、テストコードの中でincludeしているヘッダファイル名を、Mock**.hに書き換えるだけでOKです。また、モックの動作に関してはサマリを参照するのが早いと思います(需要があれば記事にしますが)。

耳より情報

ちなみに、以下行(154行目当たり)のreportの行を#でコメントアウトすると、ビルド時の結果が大人しくなります。unityに慣れた場合はコメントアウトすると気持ちよくなるかと思います。

  def execute(command_string, verbose=true)
    report command_string

次回予告?

ソースファイルをフォルダで分けている場合、CMockをそのまま使用することができませんでした。
そこで、私の場合は一部拡張コードを追加して、必要に応じて自動でフォルダを作成するようなスクリプトを作成しました。
次回はそのスクリプトを簡単に解説する予定です。
しかし、CMockについているspecやsystemtestの内容の方が面白いかもしれないので、個人的に面白い方を優先して紹介したいと思います。