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の内容の方が面白いかもしれないので、個人的に面白い方を優先して紹介したいと思います。

UnityとCMock その1

UnityとCMockの使い方について、非常に簡単に解説します。
ただし、今回ははCMock抜きで解説します。(CMockの設定はやや面倒なため)
※ここでは、2013-3-15のバージョンを使用しています。バージョンが異なる場合は設定方法が異なる可能性があります。

事前準備

まずRubyとgitをPCにインストールします。windowsでも問題なくインストールできます。

次に、gitでUnityとCMockを取得します。(CMockは今回は使用しませんが、とりあえず)
https://github.com/ThrowTheSwitch/Unity
https://github.com/ThrowTheSwitch/CMock

例えば、C:\直下あたりで、右クリックして、git bashを立ち上げて、
git clone https://github.com/ThrowTheSwitch/Unity
とすれば、GitHubから最新のUnityが取得できます。
CMockも同様に取得してください。

フォルダ構成

GitHubから取得したunityフォルダの中に、buildフォルダを作成し、次に、testフォルダの中のtestparameterized.cとtestunity.c以外を削除してください。
これで、フォルダ構成は完了です。

テストの実行条件の作成と実行方法

コマンドプロンプトで先ほど調整したunityフォルダに移動し「rake」を実行してください。ここで、赤、黄、緑の表示が出ると、設定完了です。ここで、rakeができない場合は、上記フォルダ構成が守れていないか、あるいはgccがインストールされていないか、unityのバージョンが違うかのいずれかになります。
gccは、あまり評判は良くないですが MinGW当たりで取得してください。 http://www.mingw.org/
Cygwinは評判は良いですが、インストールがMinGWに比べると多少面倒なので・・・。

テスト対象ソースコードとテストケースの作成方法

テストケースの作成方法は、Unityのdocsフォルダ内にあるサマリ、あるいはexamplesのtestフォルダ内にあるファイルを参照するのが良いと思いますが、基本的には、testフォルダ内に、test***.c というファイルを作成し、その中にtest***という関数を作成すると、自動的にそのテストが実施されます。
次に、テスト対象ソースコードの設定方法ですが、gcc_32.ymlファイルを開き、compiler:のsource_path:の後ろの方にある''で囲まれた領域に記述してください。相対パスでも絶対パスでも問題なく動作するはずです。また、必要に応じてincludes:のitem:に、パスを追加してください。
また、テスト対象のソースコードですが、config.yml中のsource_path:にパスを記入してください(面倒な場合は、とりあえずunity.cと同じsrcフォルダ内に入れることで、テストが実行可能です)。

備考

ちなみに、unityではテスト方法の変更は rakefile.rb, rakefile_helper.rb, **.yml(unityフォルダ内では、gcc_32.ymlがデフォルトで設定されています。)の3つのファイルを変更することで対処します。ただし、基本的にはconfigファイルとなる**.ymlの内容変更だけで、テスト方法を変更することが可能です。
また、テストはコマンドプロンプトでUnityフォルダまで移動し(cdコマンドなどで)、rakeコマンドを実行することで実行できます。
gcc_32.ymlは、ファイル名からするとコンパイラの設定のみ記述しているようですが、それ以外にもUnityやCMockやCeedlingの設定などをすべて記述する、非常に重要な設定ファイルになります。

次回

次は、CMockの使い方の解説を書く予定です。
CMockは強力でしかも動くとかなり感動的なので、ぜひとも使用したいところですが、いろいろと設定が手間なので、説明も一苦労です。GitHubをもう少し有効活用できると、説明も見る方も便利だと思っています。

githubとその他雑感

以前記事に書いた、softalkでパワーポイントの内容を読み上げるツールをgithubに保存しました。

https://github.com/tatssuki/ppttalk

githubに不慣れなので、とりあえず保存した、という感じですが・・・。

CMockをforkしたので、ソースコードのフォルダ構成にある程度寛容なCMockを作成して、コミットする予定です。

UnityとCppUTest part1

今、話題の書籍「テスト駆動開発による組み込みプログラミング」。
書籍の内容は非常に面白く魅力的なのですが、それを実践に移すとなると話は別です。
もっとも困難なのが、テスティングフレームワークの導入だと思われます。
また「どのテスティングフレームワークを使えば良いのか?」というツールの選定もなかなか困難です。
そこで、今回はテスティングフレームワークの簡単な比較をしてみます(基本的には人任せですが)。

上記書籍中で例に上がるテスティングフレームワークは、UnityとCppUTestの2つです。
(著者がCppUTestの作成者のひとりということで、CppUTestを推しています)
書籍中では、ストレスなく動かせるため、非常に優れたテスティングフレームワークだと記述されています。

一方で、wikipediaを確認するとC言語用のテスティングフレームワークが大量に記載されています。

ユニットテスト・フレームワーク一覧 - Wikipedia

wikipediaの○の数を見ると、c++testやTPTは多機能であり選定するならこれだ!と思いがちです。
しかし多機能になると、複数のチェックを1度のテストで実施する場合には、どうしても1回のテストに時間がかかってしまいます。
そうすると「気楽にテストする」という目的とは外れてしまいます。
また、そもそも

また他方で、Unityの公式サイトであるThrow the switchでもいくつかのテスティングフレームワークの比較をしています。
Throw The Switch! - White Papers - Comparing Unit Test Frameworks

このあたりを参考に、自分の業務に適したいテスティングフレームワークを検討すれば良いと思います。

ちなみに、私がテスティングフレームワークを検討するうえで重要だと考えている観点を以下に挙げます。

  1. テストの追加が容易であること
  2. テスト実施が容易であること
  3. MOCKファイル作成が容易であること
  4. フォルダ構造の変更が不要であること
  5. xUnit形式のxmlを出力可能なこと
  6. 有料・無料にはこだわらない(仕事で使用するため)

現在主として使用しているUnityでは、一応上記すべてを満たしており申し分ないかと考えています。
今後はCppUTestも評価し、UnityとCppUTestのどちらが、私にとって有用かを検討します。

また、上記4.のフォルダ構造の変更が不要であること、はUnityではそのままでは満たせなかったため、CMockの一部を変更する必要がありました。
そのあたりも、まとまれば公開したいと考えています。

SofTalkでパワーポイントを読み上げる

Softalkでパワーポイントのノートを読み上げるスクリプトを書いてみた。
と言っても、下記リンクを組み合わせただけで、何も新しいことをしていないけれど・・・。

[Ruby] PowerPointのノート欄を全て出力 @sarunoie
http://blog.mesh.cx/2011/02/rubyolepowerpoint.html

使い方:

  • 適当にパワーポイントを作って、話したい内容をパワーポイントの下の欄(ノート部)に書く。
  • 下のコードを適当に貼り付けて、拡張子rbのファイルを作成して、コマンドプロンプトから呼び出す
  • その際、引数として上で作成したパワーポイントファイルを渡す(このあたりの作業はドラッグアンドドロップでやると楽)
  • ソフトークが勝手に、パワーポイントで書いた内容を読み上げる(ページもめくってくれる!)
  • 途中でパワポを閉じるとバグる。プロセスが残るかも。適当なので・・・。
require 'win32ole'

# 以下、softalk引数パラメータ
softalkPath = "C:/softalk" # softalkのパス
softalkSpeed = 100.to_s
softalkVolume = 100.to_s


if ARGV.count != 1
  puts "usage: pptcmt filename"
  exit
end

filename = ARGV[0]

fso = WIN32OLE.new('Scripting.FileSystemObject')

filename = fso.getAbsolutePathName(filename)

ppt = WIN32OLE.new('PowerPoint.Application')
ppt.Visible = true

prt = ppt.Presentations.Open(filename)
count = prt.Slides.Count

view = ppt.ActivePresentation.SlideShowSettings.Run().View
view.First
system(softalkPath + "/SofTalkw.exe  /X:1")

begin
  for i in 1..count do
    targetNote = prt.Slides(i).NotesPage.Shapes.Placeholders(2).TextFrame.TextRange.Text
    result = system(softalkPath + "/SofTalkw.exe  /S:" + softalkSpeed + " /V:" + softalkVolume + " /W:" + targetNote)
    if result == true
      view.Next
    end
  end
rescue
ensure
  prt.Close
  ppt.Quit
end

このスクリプト解説用のパワポも作ったけど、とりあえずそれは社内限定公開ということで。

SysMLとソフトウェアエンジニアリング

 SysMLを使うと何が改善されるのかを、以下で書いてみます。

 

会社のおっさん達は良く、以下のようなことを言います。

・・・完全に破綻してます。

 

まず、SPLをしたいならソフトウェアのモデリングは必須であり、そのためにオブジェクト指向的考え方は必須となります(オブジェクト指向言語とか実装ではなく、オブジェクト指向設計の話)。

また、ソースコード自動生成の目的は「楽してソースコードを書くこと」ではなく、「設計と違いの無い実行体を作成すること」です。なので、ソースコードは自動で出てくるけど、漏れが無いように綿密にモデリングする必要があるのです(ExecutableUMLしかり、Matlab/Simulinkしかり)。

 

つまり、いずれにせよソフトを作るときにはもっと「別のところ」に脳みそを使えよ、という話なわけです(この件については、後ほど書く予定です)。

 

で、SysMLです。

SysMLってのは、アーキテクチャ設計に便利なツールで、ざっくり言うとUMLをシステムアーキテクチャ設計にも拡張しよう、というもののようです(ADL)。

その対象範囲ですが、オージス総研は、SysMLはシステム設計だけとしています。

http://www.ogis-ri.co.jp/event/docs/f-01e-00000288_SysML.pdf

一方テクノロジックアートは、SysMLはソフトウェア詳細設計の前までですよ、としています。

http://www.umlcert.org/news/pdf/100128_sysml_03.pdf

更に豆蔵は、テストにも使えるよ、みたいな書き方をしています。(インプットがSysMLならテストケースもSysMLに対応するのが当たり前なので、間違っていないのですが)

http://labo.mamezou.com/special/sp_018/sp_018_001.html

おそらく、全員同じことを言っていて、オージス総研の立場からすると、ソフトウェアのアーキテクチャ設計はUMLを使いましょう、という意見のような気がします。ただ、SysMLでそのままソフトウェアのアーキテクチャ設計までやれないことは無い気もするので、どちらでも良いと思います。

そもそも、ソフトウェアのアーキテクチャ設計をちゃんとUMLでやってる人は、そのままUML使えるよ、そのインプットがSysMLで明確になるよ、という感じでしょうか。

じゃあ実際にこれからSysMLを使用すると、ソフト屋さんの仕事はどう変わるのか?という話を、半分想像だけれと書いてみます。

SysMLはADLなので、ソフト設計へのインプットが変わります。つまり、UMLで設計するべき箇所と、Matlabでモデリングするべき箇所の分離が明確になります。

これはなかなか重要で、システム要求からのトレーサビリティがわかりやすくなるわけです。

 

ということで、長々とSysMLについて書きましたが、SysMLを使うと何が改善されるのか。それは、ソフトウェアのアーキテクチャ設計へのインプットが明確になる、というものだと、現段階の私は考えています。

いずれにせよ、これからのソフトウェア開発はモデリングがキーワードとして存在するわけで、いかに優れたモデリングが出来るか、というところに注力する必要があるかと思われます。

 

ちなみにデンソーは、以前の日経エレクトロニクスソースコード自動生成の話をしてた。あとで調べてみると、どうやらADLとしてmetaEdit+を使ってるっぽい。

http://www.fuji-setsu.co.jp/files/ADL_MetaEdit2010.pdf

(NEの何号の記事だったか忘れた)。

TDD4EC1

最近、Test Driven Development for Embedded Cを読んでいる。

その本によれば、組込みCにてTDDを実践するためにはUnityか、あるいはcppUTestを使用する必要があるのだが、私の場合はUnityを選択した。

その理由を以下に挙げる。

  • cpp専用ではなく、c専用であるため考え方がわかりやすい
  • rubyでいくつかの機能を拡張しており、その気になったら自分でも拡張が容易そう
  • Throw the Switchが読んでいて楽しい

ここではあえて、他の人が挙げていそうな理由は避けてみた。cppUTestとunityで悩んでいたら、ぜひunityを使ってみて。さくっと動いて非常に気持ちが良いので。

現在、Unityのsummaryを和訳しているので、気が向いたらここに上げる予定。

(Unityのsummaryに関してはシンプルでわかりやすいものの、CMockの使い方は多少骨が折れるため、いずれはそちらの和訳も公開したい)

 

それにしても、UnityやCMockに関する日本語の情報が少なすぎるのは、やはり組込マーは企業人間が多く、情報を公開できないのが原因か?