Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第14章 学習用テストと回帰テスト #18

Merged
merged 16 commits into from
Nov 10, 2017
Merged

第14章 学習用テストと回帰テスト #18

merged 16 commits into from
Nov 10, 2017

Conversation

at-grandpa
Copy link
Owner

@at-grandpa at-grandpa commented Nov 10, 2017

TODO

  • $5+10CHF=$10(レートが2:1の場合)
  • $5+$5=$10
  • $5+$5がMoneyを返す
  • Bank.reduce(Money)
  • Moneyを変換して換算を行う
  • Reduce(Bank, String)

@at-grandpa
Copy link
Owner Author

at-grandpa commented Nov 10, 2017

一旦本書とのズレを精算する。

@at-grandpa
Copy link
Owner Author

2フランを1ドルに変換するテストを書く。

@at-grandpa
Copy link
Owner Author

コンパイルエラー。

 crystal spec' <

Error in line 1: while requiring "./spec/money_package_spec.cr"

in spec/money_package_spec.cr:62: undefined method 'addRate' for MoneyPackage::Bank

      bank.addRate("CHF", "USD", 2)
           ^~~~~~~

Rerun with --error-trace to show a complete error trace.

@at-grandpa
Copy link
Owner Author

コンパイルは通るが、テストがコケる。

 crystal spec' <

.......F

Failures:

  1) MoneyPackage testReduceMoneyDifferentCurrency() 異なる通貨を計算して変換できること
     Failure/Error: result.should eq Money.dollar(1)

       Expected: #<MoneyPackage::Money:0x101c20a00 @amount=1, @currency="USD">
            got: #<MoneyPackage::Money:0x101c20a20 @amount=2, @currency="CHF">

     # spec/money_package_spec.cr:64

Finished in 1.2 milliseconds
8 examples, 1 failures, 0 errors, 0 pending

Failed examples:

crystal spec spec/money_package_spec.cr:60 # MoneyPackage testReduceMoneyDifferentCurrency() 異なる通貨を計算して変換できること

@at-grandpa
Copy link
Owner Author

at-grandpa commented Nov 10, 2017

Moneyが為替レートを知っている状態になってしまった。為替レートはBankが一手に担うべき。なので、Expressionのreduceには、Bankを引数にとらないといけない。

@at-grandpa
Copy link
Owner Author

テストが通る。

 crystal spec' <

........

Finished in 868 microseconds
8 examples, 0 failures, 0 errors, 0 pending

@at-grandpa
Copy link
Owner Author

マジックナンバーが残っているので、Bank内に表形式でデータを持ち、検索できるようにしたい。

@at-grandpa
Copy link
Owner Author

配列の等価比較がどのようになるかを学習するためのテストを書いた。crystalの場合は一致してしまうことがわかった。

とりあえず本書通り進めていくことにする。

@at-grandpa
Copy link
Owner Author

テストを消して、Pairクラスを作成する。

@at-grandpa
Copy link
Owner Author

PairクラスをHashテーブルのkeyに使うには、equalsメソッドとhashCodeメソッドを実装しないといけない。

fm
crystalだとどうなるのか検証しよう。

@at-grandpa
Copy link
Owner Author

今はPairのテストを書かない。リファクタリングの一貫でPairクラスを抽出しているから。リファクタリングが完了していれば、Pairクラスもテストできていることと同じだ。

@at-grandpa
Copy link
Owner Author

equalsメソッドとhashCodeメソッド

equalsは==でok。hashCodeはObject#hashでok。

https://crystal-lang.org/api/0.23.1/Object.html#hash-instance-method

これは、Hashのkeyの比較にも使われている。

The hash value is used along with #== by the Hash class to determine if two objects reference the same hash key.

@at-grandpa
Copy link
Owner Author

レッドバー

 crystal spec' <

......E.

Failures:

  1) MoneyPackage testReduceMoney() BankのreduceメソッドにMoneyを渡した場合い指定通貨に換算できること

       Missing hash key: #<MoneyPackage::Pair:0x1042419e0 @from="USD", @to="USD">
       0x103ba6695: *CallStack::unwind:Array(Pointer(Void)) at ??
       0x103ba6631: *CallStack#initialize:Array(Pointer(Void)) at ??
       0x103ba6608: *CallStack::new:CallStack at ??
       0x103ba2375: *raise<KeyError>:NoReturn at ??
       0x103c24ff1: *Hash(MoneyPackage::Pair, Int32)@Hash(K, V)#fetch<MoneyPackage::Pair>:Int32 at ??
       0x103c24f19: *Hash(MoneyPackage::Pair, Int32)@Hash(K, V)#[]<MoneyPackage::Pair>:Int32 at ??
       0x103c24da7: *MoneyPackage::Bank#rate<String, String>:Int32 at ??
       0x103c21e59: *MoneyPackage::Money#reduce<MoneyPackage::Bank, String>:MoneyPackage::Money at ??
       0x103c24d78: *MoneyPackage::Bank#reduce<MoneyPackage::Money, String>:MoneyPackage::Money at ??
       0x103ba4edb: ~procProc(Nil)@spec/money_package_spec.cr:53 at ??
       0x103ba437b: *it<String, String, Int32, Int32, &Proc(Nil)>:(Array(Spec::Result) | Nil) at ??
       0x103ba4e90: ~procProc(Nil)@spec/money_package_spec.cr:52 at ??
       0x103c02502: *Spec::RootContext::describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x103ba4789: *describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x103ba3f80: ~procProc(Nil)@spec/money_package_spec.cr:5 at ??
       0x103c02502: *Spec::RootContext::describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x103ba5073: *describe<MoneyPackage:Module, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x103b8dd57: __crystal_main at ??
       0x103ba1798: main at ??

Finished in 1.39 milliseconds
8 examples, 0 failures, 1 errors, 0 pending

Failed examples:

crystal spec spec/money_package_spec.cr:53 # MoneyPackage testReduceMoney() BankのreduceメソッドにMoneyを渡した場合い指定通貨に換算できること

#<MoneyPackage::Pair:0x1042419e0 @from="USD", @to="USD">の時に1を返さないとだめだが、実装されてない。テストから書こう。

@at-grandpa
Copy link
Owner Author

なるほど。予期しないエラーがでたら、まずテストを書くのか。

@at-grandpa
Copy link
Owner Author

まー確かに、そのほうが検証早いよなぁ。他のテストが落ちていないかも検証できるし。

@at-grandpa
Copy link
Owner Author

at-grandpa commented Nov 10, 2017

レッドバーが二つになった。

 crystal spec' <

......E.E

Failures:

  1) MoneyPackage testReduceMoney() BankのreduceメソッドにMoneyを渡した場合い指定通貨に換算できること

       Missing hash key: #<MoneyPackage::Pair:0x102d5c9e0 @from="USD", @to="USD">
       0x1026c4015: *CallStack::unwind:Array(Pointer(Void)) at ??
       0x1026c3fb1: *CallStack#initialize:Array(Pointer(Void)) at ??
       0x1026c3f88: *CallStack::new:CallStack at ??
       0x1026bfbc5: *raise<KeyError>:NoReturn at ??
       0x102742a81: *Hash(MoneyPackage::Pair, Int32)@Hash(K, V)#fetch<MoneyPackage::Pair>:Int32 at ??
       0x1027429a9: *Hash(MoneyPackage::Pair, Int32)@Hash(K, V)#[]<MoneyPackage::Pair>:Int32 at ??
       0x102742837: *MoneyPackage::Bank#rate<String, String>:Int32 at ??
       0x10273f8a9: *MoneyPackage::Money#reduce<MoneyPackage::Bank, String>:MoneyPackage::Money at ??
       0x102742808: *MoneyPackage::Bank#reduce<MoneyPackage::Money, String>:MoneyPackage::Money at ??
       0x1026c276b: ~procProc(Nil)@spec/money_package_spec.cr:53 at ??
       0x1026c1c0b: *it<String, String, Int32, Int32, &Proc(Nil)>:(Array(Spec::Result) | Nil) at ??
       0x1026c2720: ~procProc(Nil)@spec/money_package_spec.cr:52 at ??
       0x10271ff52: *Spec::RootContext::describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x1026c2019: *describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x1026c17d0: ~procProc(Nil)@spec/money_package_spec.cr:5 at ??
       0x10271ff52: *Spec::RootContext::describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x1026c29f3: *describe<MoneyPackage:Module, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x1026ab597: __crystal_main at ??
       0x1026befe8: main at ??

  2) MoneyPackage testIdentityRate() 同一通貨の場合はrateとして1を返すこと

       Missing hash key: #<MoneyPackage::Pair:0x102d5c8c0 @from="USD", @to="USD">
       0x1026c4015: *CallStack::unwind:Array(Pointer(Void)) at ??
       0x1026c3fb1: *CallStack#initialize:Array(Pointer(Void)) at ??
       0x1026c3f88: *CallStack::new:CallStack at ??
       0x1026bfbc5: *raise<KeyError>:NoReturn at ??
       0x102742a81: *Hash(MoneyPackage::Pair, Int32)@Hash(K, V)#fetch<MoneyPackage::Pair>:Int32 at ??
       0x1027429a9: *Hash(MoneyPackage::Pair, Int32)@Hash(K, V)#[]<MoneyPackage::Pair>:Int32 at ??
       0x102742837: *MoneyPackage::Bank#rate<String, String>:Int32 at ??
       0x1026c2972: ~procProc(Nil)@spec/money_package_spec.cr:68 at ??
       0x1026c1c0b: *it<String, String, Int32, Int32, &Proc(Nil)>:(Array(Spec::Result) | Nil) at ??
       0x1026c2940: ~procProc(Nil)@spec/money_package_spec.cr:67 at ??
       0x10271ff52: *Spec::RootContext::describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x1026c2019: *describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x1026c1850: ~procProc(Nil)@spec/money_package_spec.cr:5 at ??
       0x10271ff52: *Spec::RootContext::describe<String, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x1026c29f3: *describe<MoneyPackage:Module, String, Int32, &Proc(Nil)>:Spec::Context+ at ??
       0x1026ab597: __crystal_main at ??
       0x1026befe8: main at ??

Finished in 1.31 milliseconds
9 examples, 0 failures, 2 errors, 0 pending

Failed examples:

crystal spec spec/money_package_spec.cr:53 # MoneyPackage testReduceMoney() BankのreduceメソッドにMoneyを渡した場合い指定通貨に換算できること
crystal spec spec/money_package_spec.cr:68 # MoneyPackage testIdentityRate() 同一通貨の場合はrateとして1を返すこと

@at-grandpa
Copy link
Owner Author

グリーン。

 crystal spec' <

.........

Finished in 1.27 milliseconds
9 examples, 0 failures, 0 errors, 0 pending

@at-grandpa
Copy link
Owner Author

at-grandpa commented Nov 10, 2017

TODO

  • $5+10CHF=$10(レートが2:1の場合)
  • $5+$5=$10
  • $5+$5がMoneyを返す
  • Bank.reduce(Money)
  • Moneyを変換して換算を行う
  • Reduce(Bank, String)

@at-grandpa
Copy link
Owner Author

「これだけ今やったんだっけ?」ってなる。細かいステップに気を取られていて、全体的に今どうしているんだっけ?が迷う。

@at-grandpa
Copy link
Owner Author

こういう時は、テストをみよう。やったことがすべてそこに書かれている。

@at-grandpa
Copy link
Owner Author

TODOリストを増やすタイミングは、疑念が湧いたとき、なのかなー

@at-grandpa
Copy link
Owner Author

こういう迷いも考慮して、本書には「振り返り」があるんだろう。良いなぁ。

@at-grandpa
Copy link
Owner Author

振り返り。

  • 必要になると予想されていたパラメータ追加をすぐに行った
  • コードとテストの間のデータの重複を括りだした
  • 言語仕様を調べるテストを書いた
  • 実装内部で使うためだけのヘルパークラスを個別のテスト無しで書いた
  • リファクタリング中にミスを犯したが、問題を再現するテストを追加して、着実に前進した

@at-grandpa
Copy link
Owner Author

14章終了

@at-grandpa at-grandpa merged commit 058e8f5 into master Nov 10, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants