🔨

its v0.3.0: 追加機能と破壊的変更

2024/03/06に公開

みなさんこんにちわ、 youta-t です。
go のマッチャライブラリ its をつくってます。

https://github.com/youta-t/its

機能拡張やバグフィックスなどを含む v0.3.0 をリリースしようとしつつあります。

今日は、その v0.3.0 の変更点と、特に破壊的変更について説明します。

バグフィックス: structer & mocker

これまで structer[1] や mocker[2] では、いくつかの条件にあたる型についてマッチャやモックを生成しようとすると、うまくいきませんでした。

  • private な型を参照する型
    • 例: type S struct { Field privateType }
  • 型引数に型制約がかかっているような型
    • 例: type [T interface { ~int | ~uint }] ...
  • 他の interface を埋め込んでいる interface や、それをフィールドにもつ struct
    • type I interface { J; io.Reader }

これまでは、こうした型を含むファイルについて structer や mocker を使ってコード生成をすると、コンパイルできないファイルが生成されてしまっていました。

v0.3.0 以後は、そうした対象を含むファイルでもコンパイル可能な実装を生成するようになります。

具体的には...

  1. mocker は private な型を利用している interface や func については、モックを生成しなくなりました
  2. mocker は型制約である interface や他の interface を埋め込んでいる interface については、モックを生成しなくなりました
  3. structer は、private な型のフィールドについては、マッチャの対象としないようになりました
  4. structer は private な型を利用している interface や func のフィールドについても、マッチャの対象としないようになりました

これで、生成されたコードが参照できない型を参照しようとしてコンパイルエラーになる、ということは起きなくなるはずです。(たぶん...)

今回は仕様外とした「interface を埋め込んでいる interface」については、将来制限が緩和される可能性はあります[3]

機能拡張 & 破壊的変更: its.ClosedChan

its.ClosedChan はこれまで、受信側 channel (<-chan T)についてだけサポートしていました。

ところで、channel が閉じているかどうか判断できるのは受信側だけではありません。双方向チャネル (chan T)もそうです。

v0.3.0 からはits.ClosedChan が受信側 channel も双方向 channel も、両方ともマッチできるようになります。

ただし、この変更のために、 型引数の表現が v0.2.x 系から変化 しています。

  • これまでは its.ClosedChan[Elem] のように、channel の要素の型を型引数に指定する必要がありました。
  • これからは、 its.ClosedChan[<-chan Elem] のように、channel としての型を指定するようにしてください。

機能整理: its.Property

なにかの値についてマッチするとき、その値のもつ属性(property)について検証したいことがあります。たとえば、Stringer() な型の String() メソッドの戻り値とか。

こうしたものは、従来一度メソッドの戻り値を変数かなにかに取って、その上で its.EqEq に掛ける必要がありました。

var someStringer SomeStringer := ...

its.EqEq(want).Match(someStringer.String()).OrError(t)

しかし、そうすると、テストログとしてはただ文字列を比較しただけ、という結果しか残らず、「何の値を検証したのか?」という文脈が失われます。

こういうときに役に立つのが Property です。
これは「ある値 got から、別の値 v を取り出して、v についてマッチをかける」ということができるマッチャです。

先ほどの例は、こう書き直すことができるようになります。

someStringer := ...

its.Property(
    ".String()",
    SomeStrnger.String,
    its.EqEq(want),
)

これで、このテストケースが fail したときも、 .String() に問題があったのだ、ということがログに書き出されます。

ところで、この関数は新設されたものではありません。
もともと v0.2.x 系では itskit パッケージから公開されていたものだったのです。
しかし、この関数の有用性を鑑みて、 v0.3.0 からは 普段遣いするパッケージである its に移動することにしました。

Deprecated: its.EqEqPtr

v0.3.0でits.EqEqPtr を Deprecated に指定します。

というのも、its.Pointer というマッチャが入ったことが原因です。
its.EqEqPtrits.Pointer と機能が重複しているうえに、カバーしている範囲が小さいです。

これまで 次のように書いていたテストは...

its.EqEqPtr(want).Match(got).OrError(t)

v0.3.0 以後は

its.Pointer(its.EqEq(*want)).Match(got).OrError(t)

と書き直すことをおすすめします。

まとめ

...と、以上の変更を含む v0.3.0 を公開しようとしています。何事もなければ、 明日にも公開される 見通しです。

追記

以上の内容のほか、 シナリオテスト(its/mocker/scenario)の Next の戻り値も変更しようと考えています。
これまで、

token, trackedFn := scenario.Next(dsc, fnImpl)

としてきましたが、 token 側に今のところ需要がありません。これを削除しようと考えています。

脚注
  1. github.com/youta-t/its/structer ↩︎

  2. github.com/youta-t/its/mocker ↩︎

  3. とはいえ、別のパッケージで定義されているインタフェースの定義を再帰的に読みに行くような振る舞いが必要で、すぐには難しそうです。 ↩︎

Discussion