ようへいの日々精進XP

よかろうもん

mruby-mrbgem-template で mrbgem を TDD してみるメモ

tl;dr

hb.matsumoto-r.jp

blog.matsumoto-r.jp

上記の二つの記事を参考にさせて頂きながらサンプルの mrbgem を TDD で作ってみたのでメモ。 @matsumotory さんには超感謝。

以下、サンプル。

github.com

のアイコンが嬉しい。


memo

mruby-mrbgem-template で mrbgem の雛形を作る

mruby-mrbgem-template という mrbgem の雛形を作る mrbgem を使って雛形を作成する。mruby-mrbgem-template 自体の導入について以下をご一読下さい。

github.com

mruby-mrbgem-template を導入したら以下のような Ruby ファイルを作る。

params = {  
  :mrbgem_name    => 'mruby-sample',
  :license        => 'MIT',
  :github_user    => 'inokappa',
  :mrbgem_prefix  => '../../myrepo',
  :class_name     => 'Sample',
  :author         => 'Yohei Kawahara',
}

c = MrbgemTemplate.new params
c.create

このファイルを以下のように実行する。

$ ./bin/mruby create.rb

実行すると ../../myrepo 以下に mruby-sample というファイルが生成される。

% ls -l ../../myrepo/mruby-sample
total 32
-rw-r--r--  1 kappa  staff  1142 Nov  1 09:47 LICENSE
-rw-r--r--  1 kappa  staff   503 Nov  1 09:47 README.md
-rw-r--r--  1 kappa  staff   204 Nov  1 12:53 mrbgem.rake
drwxr-xr-x  4 kappa  staff   136 Nov  1 12:56 mrblib
-rw-r--r--  1 kappa  staff   189 Nov  1 09:47 mruby-sample.gem
drwxr-xr-x  4 kappa  staff   136 Nov  1 09:47 src
drwxr-xr-x  4 kappa  staff   136 Nov  1 12:56 test

test を書く

以下のようなファイルが ./test/mrb_sample.rb に生成されている。

##
## Sample Test
##

assert("Sample#hello") do
  t = Sample.new "hello"
  assert_equal("hello", t.hello)
end

assert("Sample#bye") do
  t = Sample.new "hello"
  assert_equal("hello bye", t.bye)
end

assert("Sample.hi") do
  assert_equal("hi!!", Sample.hi)
end

このファイルを以下のように書き換える。

##
## Sample Test
##

assert("Sample#hello") do
  t = Sample.new("hello")
  assert_equal("Say hello", t.hello)
end

初めてのテスト

(snip)

  # conf.gem :git => 'https://github.com/iij/mruby-io.git'
  # conf.gem :git => 'https://github.com/iij/mruby-dir.git'
  # conf.gem :git => 'https://github.com/matsumoto-r/mruby-mrbgem-template.git'
  # 以下を追記
  conf.gem '../../myrepo/mruby-sample'
  conf.enable_test

(snip)

以下のようにテストを実行。

$ rake clean ; rake all test

以下のようにテストがコケる。

(snip)

>>> Test host <<<
mrbtest - Embeddable Ruby Test

...............................................................................................................................................................................................................................................................................................................................................................................................................?............................................................................................................................................................................................?...............................................................F...................................................................................................................................................................................................................................................................................................................
Skip: Module#prepend super in alias  super does not currently work in aliased methods
Skip: File.expand_path (with ENV)  
Fail: Sample#hello (mrbgems: mruby-sample)
 - Assertion[1] Failed: Expected to be equal
    Expected: "Say hello"
      Actual: "hello"
Total: 958
   OK: 957
   KO: 1
Crash: 0
 Time: 0.36 seconds
rake aborted!

(snip)

ここで怯まず mruby コードを修正する。

mruby コードの修正

テストの結果を受けて mruby のコードを修正する。mruby のコードは特に弄っていなかったので以下のような状態になっている。

class Sample
  def bye
    self.hello + " bye"
  end
end

このコードを以下のように修正する。

class Sample
  def initialize(data)
    @data = data
  end

  def hello
    "Say " + @data
  end
end

改めてテスト

$ rake clean ; rake all test

以下の通りテストが通る。

(snip)

>>> Test host <<<
mrbtest - Embeddable Ruby Test

...............................................................................................................................................................................................................................................................................................................................................................................................................?............................................................................................................................................................................................?...................................................................................................................................................................................................................................................................................................................................................................................
Skip: Module#prepend super in alias  super does not currently work in aliased methods
Skip: File.expand_path (with ENV)  
Total: 958
   OK: 958
   KO: 0
Crash: 0
 Time: 0.38 seconds

>>> Test test <<<
mrbtest - Embeddable Ruby Test

...............................................................................................................................................................................................................................................................................................................................................................................................................?..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Skip: Module#prepend super in alias  super does not currently work in aliased methods
Total: 881
   OK: 881
   KO: 0
Crash: 0
 Time: 0.29 seconds

.............
Total: 13
   OK: 13
   KO: 0
Crash: 0
 Time: 0.4 seconds

追加で Openweathermap にアクセスしてレスポンスを出力する実装

まずは以下のようなテストを書く。

assert("Sample#access") do
  t = Sample.new("bye")
  assert_include("Fukuoka-shi", JSON::parse(t.access("Fukuoka-shi").body)['name'])
end

これは Openweathermap の API に以下のようにアクセスしてレスポンスをチェック、レスポンスに Fukuoka-shi が含まれることを期待している。

$ curl -s 'http://api.openweathermap.org/data/2.5/weather?q=Fukuoka-shi&appid=bd82977b86bf27fb59a04b61b657fb6f'

appid=bd82977b86bf27fb59a04b61b657fb6fここから拝借。

追加実装をテストする前に

追加実装についてテストをする前にテストを行う為には以下の mrbgem が必要になる。

  • mruby-httprequest
  • mruby-json

テスト実施に際して依存している mrbgem は mrbgem.rake ファイルに以下の通りに記載する。

MRuby::Gem::Specification.new('mruby-sample') do |spec|
  spec.license = 'MIT'
  spec.authors = 'Yohei Kawahara'
  spec.add_test_dependency 'mruby-httprequest'
  spec.add_test_dependency 'mruby-json'
end

テストする

テストをする。

$ rake clean ; rake all test

(snip)

>>> Test host <<<
mrbtest - Embeddable Ruby Test

...............................................................................................................................................................................................................................................................................................................................................................................................................?............................................................................................................................................................................................?...................................................................................................................................X..................................................................................................................................................................................................................................................................................................................
Skip: Module#prepend super in alias  super does not currently work in aliased methods
Skip: File.expand_path (with ENV)  
NoMethodError: Sample#access => undefined method 'access' for #<Sample:0x7fdda480cc20 @data="bye"> (mrbgems: mruby-sample)
Total: 1025
   OK: 1024
   KO: 0
Crash: 1
 Time: 0.47 seconds
rake aborted!

(snip)

当然、コケる。

mruby コードを実装する

以下のように実装する。

class Sample
  def initialize(data)
    @data = data
    @url = "http://api.openweathermap.org/data/2.5/weather"
  end

  def hello
    "Say " + @data
  end

  def access(city)
    http = HttpRequest.new()
    url = @url + '?q=' + city + '&appid=bd82977b86bf27fb59a04b61b657fb6f'
    http.get(url)
  end
end

改めてテスト

$ rake clean ; rake all test

(snip)

>>> Test host <<<
mrbtest - Embeddable Ruby Test

...............................................................................................................................................................................................................................................................................................................................................................................................................?............................................................................................................................................................................................?......................................................................................................................................................................................................................................................................................................................................................................................................................................................
Skip: Module#prepend super in alias  super does not currently work in aliased methods
Skip: File.expand_path (with ENV)  
Total: 1025
   OK: 1025
   KO: 0
Crash: 0
 Time: 1.07 seconds

>>> Test test <<<
mrbtest - Embeddable Ruby Test

...............................................................................................................................................................................................................................................................................................................................................................................................................?..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Skip: Module#prepend super in alias  super does not currently work in aliased methods
Total: 881
   OK: 881
   KO: 0
Crash: 0
 Time: 0.29 seconds

.............
Total: 13
   OK: 13
   KO: 0
Crash: 0
 Time: 0.46 seconds

テスト通った。

Travis CI でテスト

mruby-mrbgem-template でひな形を生成すると .travis.yml とうファイルと .travis_build_config.rb というファイルが生成されている。それぞれの中身は以下の通り。

language: c
compiler:
  - gcc
  - clang
before_install:
    - sudo apt-get -qq update
install:
    - sudo apt-get -qq install rake bison git gperf
before_script:
  - cd ../
  - git clone https://github.com/mruby/mruby.git
  - cd mruby
  - cp -fp ../mruby-sample/.travis_build_config.rb build_config.rb
script:
  - make all test
MRuby::Build.new do |conf|
  toolchain :gcc
  conf.gembox 'default'
  conf.gem '../mruby-sample'
  conf.enable_test
end

事前に Githubリポジトリを作成し Travis CI と連携しておいて Github に push すると...

f:id:inokara:20151101135928p:plain

やったー。Travis CI でもテストが通った。

残るは mgem-list への登録

作った mrbgem は以下のような YAML ファイルを書いて mgem-list にプルリクエストを投げる。(今回はサンプルなので投げない)

name: mruby-sample
description: Sample
author: Yohei Kawahara
website: https://github.com/inokappa/mruby-sample
protocol: git
repository: https://github.com/inokappa/mruby-sample.git
dependencies:
- mruby-httprequest
- mruby-json

以上

改めて

  • Blog 記事を書いて下さった @matsumotory さんに感謝!
  • mruby-mrbgem-template 使えばテストまで含めた mrbgem の雛形が作られるので嬉しい!