(Translated by https://www.hiragana.jp/)
今夜あなたは目撃者!テストノ治安ヲ再生セヨ!
2023/12/05

今夜こんやあなたは目撃もくげきしゃ!テストノ治安ちあん再生さいせいセヨ!

この記事きじは、"Go 言語げんごAdvent Calendar 2023 シリーズ 2" 5にちになります。


こんばんは!はじめて Go のアドベントカレンダーにエントリーしました。@bayashiもうします。はじめてなのでタイトルにインパクトがしくて気合きあれたんですが、とくにアイデアがかばず、みのもんたさんインスパイアになってしまいました。わからないひとはそのままスルーしてすすめてもらって大丈夫だいじょうぶです。ふか意味いみはありません。

開発かいはつしゃはテストの失敗しっぱい目撃もくげきする!

さて、みなさんのなかには業務ぎょうむで Go をいているひとおおいかとおもいます。わたしもそうです。なんらかのアプリケーションを開発かいはつして、もちろんテストもいているとおもいます。業務ぎょうむでの開発かいはつとなると、チームでむことがおおいのではないでしょうか。チームでコードをくと、その一貫いっかんせいについて問題もんだいがでやすくなります。本体ほんたいコードでもそうですが、テストにおいてもしかりです。そしてわたし今回こんかい 注目ちゅうもくしたのが、テストが失敗しっぱいしたときの出力しゅつりょくについてです。

とくに Go においてはテーブルドリブンテストが推奨すいしょうされていることもあり、条件じょうけん複雑ふくざつになりがちで、fail したときの出力しゅつりょく内容ないよう充分じゅうぶんではなく、なにきたのかさっぱりわかりにくいということがまれによくあります。え、ありませんか? ありますよね? あるでしょう?

もちろん、テーブルドリブンでなくてもこけてこまることは多々たたあります。テストの失敗しっぱい情報じょうほう典型てんけいてき不足ふそくしがちなのです。

そうした問題もんだいは、アサーションライブラリを利用りようしていると一定いってい解決かいけつされます。テストの実行じっこうからこけたときの出力しゅつりょくまでおおむね面倒めんどうてもらえるからです。しかし、Goにおいてはアサーションライブラリが推奨すいしょうされていません。Goのほかおぼえることがえないほうがいいとか、エラーやそのレポートは自力じりきでハンドリングしなきゃだめよ、というおぼしめしがあるからです。

そのてんについて、わたし異論いろんありません。

テストの治安ちあん

しかし、テストがこけてこまる現実げんじつはけっこう深刻しんこくです。こけたらなおさなければなりません。チーム開発かいはつにおいては、もういないだれかがいたテストをることもおおいでしょう。そしておおむね複雑ふくざつでわかりにくい部分ぶぶんおくおくがこけるのです。そもそも、こけたときのレポートはおろかになりがちだときました。オリジナルでテストをいたひと以外いがいはこけたところをることがすくないので、こけたときの状態じょうたい問題もんだいがあってもレビューですりけやすいのです。カバレッジの計測けいそくはありますが、テストがこけたときのレポートが十分じゅうぶんかどうかは機械きかいてき判断はんだんするのがむずかしいのです。あるときテストがこけて、そのときはじめてレポートが十分じゅうぶんでないことにづいてそら見上みあげることになるのです。あーやれやれ。

テストがこけたとき、このテストは何者なにもので、検査けんさしたなにだったのか、typeは? 2比較ひかくなら差分さぶんは?なまデータでは?Dumpは?修正しゅうせいするためになにをすべきなのか? いつかのこけるときそなえて、そういうのを逐一ちくいち毎回まいかい丁寧ていねいくのはほねれます。パスしているあいだ必要ひつようがないけれど、ひとたびこけるといちじるしく存在そんざいもとめられるのです。テストがこけたときのレポートに安定あんていして必要ひつようなものがふくまれる、そういう状態じょうたいをつくるためのものがあれば、テストの治安ちあん向上こうじょうするんじゃないか?

test fail なんてこわくない

そこでいてみたのが、Witness (目撃もくげきしゃ)というヘルパーです。

以下いかのように使つかいます。簡単かんたんです。

package main

import (
    "testing"

    w "github.com/bayashi/witness"
)

func TestExample(t *testing.T) {
    g := "a\nb\nc"
    e := "a\nd\nc"

    if g != e {
        w.Got(g).Expect(e).Fail(t, "Not same")
    }
}

あまり説明せつめいする必要ひつようもないとおもいますが、以下いかいちぎょうで、テスト対象たいしょうの2設定せっていして、Fail メソッドにこける理由りゆうわたしつつします。

w.Got(g).Expect(e).Fail(t, "Not same")

ターミナルでの出力しゅつりょく以下いかのようになります。

Trace:          /home/usr/go/src/github.com/bayashi/witness/witness_test.go:14
Fail reason:    Not same
Type:           Expect:string, Got:string
Expected:       "a\nd\nc"
Actually got:   "a\nb\nc"

GotExpectanyなんでもけて、レポート出力しゅつりょくするさいによしなにやすい、比較ひかくしやすい形式けいしきにします。

さらに、もっとこまかいちがいの確認かくにんをしたいときは、 ShowMore() というメソッドをんでおくと、

w.Got(g).Expect(e).ShowMore().Fail(t, "Not same")

以下いかのように diff や なまデータでの表示ひょうじえます。

Trace:          /home/usr/go/src/github.com/bayashi/witness/witness_test.go:14
Fail reason:    Not same
Type:           Expect:string, Got:string
Expected:       "a\nd\nc"
Actually got:   "a\nb\nc"
Diff details:   --- Expected
                +++ Actually got
                @@ -1,3 +1,3 @@
                 a
                -d
                +b
                 c
Raw Expect:     ---
                a
                d
                c
                ---
Raw Got:        ---
                a
                b
                c
                ---

上記じょうきれいはテストしている文字もじれつですが、その複雑ふくざつかた構造こうぞうたい場合ばあいは、spew.Sdump した結果けっか表示ひょうじするかんじになります。

その 詳細しょうさいなメソッドはこちら をごらんください。テストめいやオリジナルの項目こうもく追加ついかすることもできるようになっています。

inspired by testify

さて、この fail レポートですが、どこかでみたことありますよね?

そうです。もと挙動きょどうtestify から拝借はいしゃくしていて、過去かこ自分じぶんのアサーションライブラリいたときにまとめたのを、今回こんかいもういち整理せいり整頓せいとんして、fail reportライブラリとしてしました。

まだひととおいてそこそこうごきました、という状態じょうたいなのですが、よろしければおためしください。こけたときの記述きじゅつかんがえるりょう圧倒的あっとうてきってらくにれるとおもいます。また、いまはターミナルに出力しゅつりょくして人間にんげんむことを想定そうていした出力しゅつりょくをしますが、今後こんごはGithub Actionsのアノテーションにも対応たいおうしたいなあとおもっています。

ぜひ、ご意見いけん感想かんそうなどいただけるとうれしいです。

今夜こんやあなたは目撃もくげきしゃ!テストノ治安ちあん再生さいせいセヨ! Witness

おわり。

サイトない検索けんさく