カードゲームを作る　その６（戦闘API　UT）

##この記事は
とある[カードゲーム](http://arcana.vector.co.jp)が非常に面白く、
そのゲームの見た目クローンを作ろうと一人のプログラマーが奮闘していくブログのような記事です。

その４の続き
ここでは、戦闘APIのユニットテストをしていきます。

##ユニットテストの作成
初回は種族間の優位性の確認だけで勝敗を決めるようにします。
それから徐々に拡張していきます。
ちなみに種族間の優劣は以下の仕様とします。

1=王国、2=精霊、3=蛮族、4=幽魔、97=魔王、98=万能、100=魔神

|（強）→（弱）|
|:------:|
|王国→幽魔|
|幽魔→精霊|
|精霊→蛮族|
|蛮族→王国|

##API作成

```bash:BattleAPIの作成
$  rails g scaffold_controller Battle ID:string Btype:string BTarget:string V:string UA:string
```
```
Running via Spring preloader in process 58697
      create  app/controllers/battles_controller.rb
      invoke  test_unit
      create    test/controllers/battles_controller_test.rb
```

##ユニットテスト
###何はともあれ、動かしてみた

```bash:１回目の失敗
$ ruby test/controllers/battles_controller_test.rb
/Users/*****/.rbenv/versions/2.1.5/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- test_helper (LoadError)
```

エラーメッセージに「cannot load such file -- test_helper」と出てるので、
その通り対応します。
対応：test_helper をインストール

```bash:２回目の失敗
$ rake test
rake aborted!
ActiveRecord::AdapterNotSpecified: 'test' database is not configured. Available: ["default", "development"]
/test/test_helper.rb:3:in `<top (required)>'
/test/controllers/battles_controller_test.rb:1:in `<top (required)>'
Tasks: TOP => test:run
(See full trace by running task with --trace)
```

対応：config/database.yml にtest:〜を追記しました。

###テスト環境のまとめ
```bash:test_helperインストール
$ gem install test_helper
```
```ruby:config/database.yml(再録)
test:
  <<: *default
  database: db/test.sqlite3
```

###動かしてみる（１発目）

```bash:とりあえずなテスト結果
$ rake test
Run options: --seed 50643

# Running:

.....EEEEE

Finished in 0.253902s, 39.3853 runs/s, 31.5082 assertions/s.

  1) Error:
BattlesControllerTest#test_should_create_battle:
NoMethodError: undefined method `battles' for #<BattlesControllerTest:0x007f8efcfcc528>
    test/controllers/battles_controller_test.rb:5:in `block in <class:BattlesControllerTest>'


  2) Error:
BattlesControllerTest#test_should_show_battle:
NoMethodError: undefined method `battles' for #<BattlesControllerTest:0x007f8efcfb4478>
    test/controllers/battles_controller_test.rb:5:in `block in <class:BattlesControllerTest>'


  3) Error:
BattlesControllerTest#test_should_update_battle:
NoMethodError: undefined method `battles' for #<BattlesControllerTest:0x007f8efcfac700>
    test/controllers/battles_controller_test.rb:5:in `block in <class:BattlesControllerTest>'


  4) Error:
BattlesControllerTest#test_should_get_index:
NoMethodError: undefined method `battles' for #<BattlesControllerTest:0x007f8efcfa47a8>
    test/controllers/battles_controller_test.rb:5:in `block in <class:BattlesControllerTest>'


  5) Error:
BattlesControllerTest#test_should_destroy_battle:
NoMethodError: undefined method `battles' for #<BattlesControllerTest:0x007f8efcf9c580>
    test/controllers/battles_controller_test.rb:5:in `block in <class:BattlesControllerTest>'

10 runs, 8 assertions, 0 failures, 5 errors, 0 skips
```

当然実装してないからエラーが出まくってますが、
ここまでDBのデータ作成以外、ほぼテンプレートに沿って
作っただけでここまでやれるのかと感じました。

ユニットテストの中身を記述についてはまた次の記事に書きます。

##余談
前々回あたりで試験的に動かしたmonster_infosについて、
fixturesを設定したので、テスト環境で動かすと登録した内容が返ってきます。

```bash:テスト環境で起動する
$ RAILS_ENV=test rails server
$ curl http://localhost:3000/monsters_infos/
[{"id":113629430,"CardId":"T03","Name":"蛮族の負け組","Hp":1,"Atk":1,"Cost":1,"Wait":1,"Lv":1,"Exp":1,"Rare":1,"Race":3,"ImageId":"MyString","SkillNos":"MyString","Lv1":null,"Hp1":null,"Atk1":null,"Cost1":null,"Wait1":null,"Exp1":null,"Lv2":null,"Hp2":null,"Atk2":null,"Cost2":null,"Wait2":null,"Exp2":null,"Lv3":null,"Hp3":null,"Atk3":null,"Cost3":null,"Wait3":null,"Exp3":null,"Lv4":null,"Hp4":null,"Atk4":null,"Cost4":null,"Wait4":null,"Exp4":null,"Lv5":null,"Hp5":null,"Atk5":null,"Cost5":null,"Wait5":null,"Exp5":null,"Lv6":null,"Hp6":null,"Atk6":null,"Cost6":null,"Wait6":null,"Exp6":null,"Lv7":null,"Hp7":null,"Atk7":null,"Cost7":null,"Wait7":null,"Exp7":null,"Lv8":null,"Hp8":null,"Atk8":null,"Cost8":null,"Wait8":null,"Exp8":null,"Lv9":null,"Hp9":null,"Atk9":null,"Cost9":null,"Wait9":null,"Exp9":null,"Lv10":null,"Hp10":null,"Atk10":null,"Cost10":null,"Wait10":null,"Exp10":null,"Lv11":null,"Hp11":null,"Atk11":null,"Cost11":null,"Wait11":null,"Exp11":null,"Lv12":null,"Hp12":null,"Atk12":null,"Cost12":null,"Wait12":null,"Exp12":null,"Lv13":null,"Hp13":null,"Atk13":null,"Cost13":null,"Wait13":null,"Exp13":null,"Lv14":null,"Hp14":null,"Atk14":null,"Cost14":null,"Wait14":null,"Exp14":null,"Lv15":null,"Hp15":null,"Atk15":null,"Cost15":null,"Wait15":null,"Exp15":null,"created_at":"2016-01-27T15:33:47.000Z","updated_at":"2016-01-27T15:33:47.000Z"},{"id":281110143,"CardId":"T04","Name":"幽魔の負け組","Hp":1,"Atk":1,"Cost":1,"Wait":1,"Lv":1,"Exp":1,"Rare":1,"Race":4,"ImageId":"MyString","SkillNos":"MyString","Lv1":null,"Hp1":null,"Atk1":null,"Cost1":null,"Wait1":null,"Exp1":null,"Lv2":null,"Hp2":null,"Atk2":null,"Cost2":null,"Wait2":null,"Exp2":null,"Lv3":null,"Hp3":null,"Atk3":null,"Cost3":null,"Wait3":null,"Exp3":null,"Lv4":null,"Hp4":null,"Atk4":null,"Cost4":null,"Wait4":null,"Exp4":null,"Lv5":null,"Hp5":null,"Atk5":null,"Cost5":null,"Wait5":null,"Exp5":null,"Lv6":null,"Hp6":null,"Atk6":null,"Cost6":null,"Wait6":null,"Exp6":null,"Lv7":null,"Hp7":null,"Atk7":null,"Cost7":null,"Wait7":null,"Exp7":null,"Lv8":null,"Hp8":null,"Atk8":null,"Cost8":null,"Wait8":null,"Exp8":null,"Lv9":null,"Hp9":null,"Atk9":null,"Cost9":null,"Wait9":null,"Exp9":null,"Lv10":null,"Hp10":null,"Atk10":null,"Cost10":null,"Wait10":null,"Exp10":null,"Lv11":null,"Hp11":null,"Atk11":null,"Cost11":null,"Wait11":null,"Exp11":null,"Lv12":null,"Hp12":null,"Atk12":null,"Cost12":null,"Wait12":null,"Exp12":null,"Lv13":null,"Hp13":null,"Atk13":null,"Cost13":null,"Wait13":null,"Exp13":null,"Lv14":null,"Hp14":null,"Atk14":null,"Cost14":null,"Wait14":null,"Exp14":null,"Lv15":null,"Hp15":null,"Atk15":null,"Cost15":null,"Wait15":null,"Exp15":null,"created_at":"2016-01-27T15:33:47.000Z","updated_at":"2016-01-27T15:33:47.000Z"},{"id":298486374,"CardId":"T02","Name":"精霊の負け組","Hp":1,"Atk":1,"Cost":1,"Wait":1,"Lv":1,"Exp":1,"Rare":1,"Race":2,"ImageId":"MyString","SkillNos":"MyString","Lv1":null,"Hp1":null,"Atk1":null,"Cost1":null,"Wait1":null,"Exp1":null,"Lv2":null,"Hp2":null,"Atk2":null,"Cost2":null,"Wait2":null,"Exp2":null,"Lv3":null,"Hp3":null,"Atk3":null,"Cost3":null,"Wait3":null,"Exp3":null,"Lv4":null,"Hp4":null,"Atk4":null,"Cost4":null,"Wait4":null,"Exp4":null,"Lv5":null,"Hp5":null,"Atk5":null,"Cost5":null,"Wait5":null,"Exp5":null,"Lv6":null,"Hp6":null,"Atk6":null,"Cost6":null,"Wait6":null,"Exp6":null,"Lv7":null,"Hp7":null,"Atk7":null,"Cost7":null,"Wait7":null,"Exp7":null,"Lv8":null,"Hp8":null,"Atk8":null,"Cost8":null,"Wait8":null,"Exp8":null,"Lv9":null,"Hp9":null,"Atk9":null,"Cost9":null,"Wait9":null,"Exp9":null,"Lv10":null,"Hp10":null,"Atk10":null,"Cost10":null,"Wait10":null,"Exp10":null,"Lv11":null,"Hp11":null,"Atk11":null,"Cost11":null,"Wait11":null,"Exp11":null,"Lv12":null,"Hp12":null,"Atk12":null,"Cost12":null,"Wait12":null,"Exp12":null,"Lv13":null,"Hp13":null,"Atk13":null,"Cost13":null,"Wait13":null,"Exp13":null,"Lv14":null,"Hp14":null,"Atk14":null,"Cost14":null,"Wait14":null,"Exp14":null,"Lv15":null,"Hp15":null,"Atk15":null,"Cost15":null,"Wait15":null,"Exp15":null,"created_at":"2016-01-27T15:33:47.000Z","updated_at":"2016-01-27T15:33:47.000Z"},{"id":980190962,"CardId":"T01","Name":"王国の負け組","Hp":1,"Atk":1,"Cost":1,"Wait":1,"Lv":1,"Exp":1,"Rare":1,"Race":1,"ImageId":"MyString","SkillNos":"MyString","Lv1":null,"Hp1":null,"Atk1":null,"Cost1":null,"Wait1":null,"Exp1":null,"Lv2":null,"Hp2":null,"Atk2":null,"Cost2":null,"Wait2":null,"Exp2":null,"Lv3":null,"Hp3":null,"Atk3":null,"Cost3":null,"Wait3":null,"Exp3":null,"Lv4":null,"Hp4":null,"Atk4":null,"Cost4":null,"Wait4":null,"Exp4":null,"Lv5":null,"Hp5":null,"Atk5":null,"Cost5":null,"Wait5":null,"Exp5":null,"Lv6":null,"Hp6":null,"Atk6":null,"Cost6":null,"Wait6":null,"Exp6":null,"Lv7":null,"Hp7":null,"Atk7":null,"Cost7":null,"Wait7":null,"Exp7":null,"Lv8":null,"Hp8":null,"Atk8":null,"Cost8":null,"Wait8":null,"Exp8":null,"Lv9":null,"Hp9":null,"Atk9":null,"Cost9":null,"Wait9":null,"Exp9":null,"Lv10":null,"Hp10":null,"Atk10":null,"Cost10":null,"Wait10":null,"Exp10":null,"Lv11":null,"Hp11":null,"Atk11":null,"Cost11":null,"Wait11":null,"Exp11":null,"Lv12":null,"Hp12":null,"Atk12":null,"Cost12":null,"Wait12":null,"Exp12":null,"Lv13":null,"Hp13":null,"Atk13":null,"Cost13":null,"Wait13":null,"Exp13":null,"Lv14":null,"Hp14":null,"Atk14":null,"Cost14":null,"Wait14":null,"Exp14":null,"Lv15":null,"Hp15":null,"Atk15":null,"Cost15":null,"Wait15":null,"Exp15":null,"created_at":"2016-01-27T15:33:47.000Z","updated_at":"2016-01-27T15:33:47.000Z"}]
```

-----
いくつか言い訳

* 不定期連載です。
* 多分途中で挫折します。
* 筆者のメモも兼ねているため過去の記事も遠慮なく随時編集いたします。
* プログラミングの開発経験はあってもゲームの開発経験はこれが初めてです。

等色々ありますが、生暖かい目で応援してくださると光栄です。