最近、外出先failpiontに関するいくつかの情報を学んだし、今それを共有したいと思います。
FailPiontは、自動テストの障害をシミュレートするために使用されます
自動テストは、多くの場合、いくつかの障害状態をシミュレートするために、その後、障害が私たちの考えに基づいて適切に実行するかどうかを、この場合には、当社の手続きをテストする必要があります。いくつかの障害がテストコードのシミュレーションに簡単ですが、このような切断されたネットワーク・インタフェース・トラフィックなどのいくつかの比較的くんダンは、同様のオーバーランがあります。そして、FailPiont外に従事するための素晴らしい神があります。
Etcdが行わgofail https://github.com/etcd-io/gofail
gofailが使用されています
FUNC someFunc()文字列{ // gofailます。var SomeFuncString文字列 // // failpointがトリガされたときに、これはSomeFuncStringcalledさ SomeFuncString返す// リターン"default"を }
シミュレートされた失敗のコードを書くために、コードはコメントアウト。我々は、コマンドを有効にgofail実行をテストする場合、コードはそうなっています
FUNC someFunc()文字列{ 場合vSomeFuncString、__fpErr:= __fp_SomeFuncString.Acquire()。__fpErr ==ゼロ{__fp_SomeFuncString.Release()を延期します。SomeFuncString、__fpTypeOK:= vSomeFuncString(ストリング)。もし__ fpTypeOK {goto文__badTypeSomeFuncString}! failpointがトリガされたとき//これがSomeFuncStringcalledされる リターンSomeFuncStringを。__badTypeSomeFuncString:__fp_SomeFuncString.BadType(vSomeFuncString、 "文字列"); }。 "default"を返します }
生成されたファイルもあります
// GOFAILによって生成されます。編集しないでください。 パッケージfail_pointの インポート"github.com/etcd-io/gofail/runtime" のvar __fp_SomeFuncString * runtime.Failpoint = runtime.NewFailpoint( "fail_point"、 "SomeFuncString")
その後、我々はテストコードを書きます
FUNC Test_someFunc(T * testing.T){ // /ユーザ/ EDZ /ドキュメントは/ dev /メトリック/ SRC / fail_point / gofail.Enable( "fail_point / SomeFuncString"、 `リターン( "SomeFuncStringは")`) gofail.Disableを延期します( "fail_point / SomeFuncString") 試験:= []構造体{ 名文字列が 文字列を必要 } { {名: "パス"は、望む: "SomeFuncStringを"}、 } ため_、TT =レンジテスト{ t.Run(TT。名前、FUNC(T * testing.T){ 得た場合:= someFunc(); = tt.want {ました! t.Errorf( "someFunc()=%vを、%vをしたい"、tt.wantを得ました) } }) } }
渡された、いくつかのテストを実行します。
そして生成されたコードの可読性が悪い。しかし、このgofailはまた、このようなコメントの存在がエラーを見つけることは容易ではないとして、いくつかの欠点を持っています。
これらの問題を解決するには、pingcap同社はgofail ==「failpiontのアップグレード版を作りました
このようなコードはfailpiontです
FUNC pingCapFail()(文字列、failpoint.Value){ failpoint.Inject( "failpoint名"、FUNC(ヴァルfailpoint.Value){ failpoint.Return( "ユニットテスト"、ヴァル) }) リターン"成功"、ゼロ } pingCapFail1 FUNC()文字列{ failpoint.Inject( "failpoint-NAME1"、FUNC(){ failpoint.Return( "ユニットテスト") }) リターン"成功" } pingCapFail2(CTX context.Context)FUNC(文字列、failpoint .VALUE){ failpoint.InjectContext(CTX、 "failpoint-NAME2"、FUNC(ヴァルfailpoint.Value){ failpoint.Return( "ユニットテスト"、ヴァル) }) リターン"成功"、ゼロ }
私たちは、達成するために、アノテーションを使用しての欠点を回避failpiont、参照するだけでなく、コードの実行に影響を与えるためにいくつかのコードを挿入することができます。
これは、テストでは複数の同時テストケースを可能にするさまざまなユースケースといくつかの障害がトリガされる、いくつかの障害を無視します。
実行failpoint-CTLを有効にするには、コマンドを有効にします
コードはこのようになっています。この時間
FUNC pingCapFail()(文字列、failpoint.Value){ もしヴァル、OK:= failpoint.Eval(_curpkg _( "failpoint名")); OK { リターン"ユニットテスト"、ヴァル } リターン"成功"、ゼロ } pingCapFail1()文字列{FUNC _場合、OK:= failpoint.Eval(_curpkg _( "failpoint-NAME1"))。OK { リターン"ユニットテスト" } 戻り"成功" } pingCapFail2(CTX context.Context)FUNC(文字列、failpoint.Value){ もしヴァル、OK:= failpoint.EvalContext(CTX、_curpkg _( "failpoint-NAME2") ); OK { リターン「ユニットテスト」、ヴァル } リターン「成功」、ゼロ }
コードの可読性も高いときにこれは見ることができます。
その後、我々はいくつかのテストコードを書きます
FUNC Test_pingCapFail(T * testing.T){ テスト:= []構造体{ 名文字列 の文字列が欲しい failpoint.Valueをwant1 } { {名: "pingCapFail"は、望む: "ユニットテスト"、want1:5} } failpointを。イネーブル( "fail_point / failpoint名"、 "リターン(5)") _、TTのために:=範囲のテスト{ t.Run(tt.name、FUNC(T * testing.T){ 得た、GOT1:= pingCapFail( ) 得た場合!= tt.want { t.Errorf( "pingCapFail()だ=%V、欲しい%V"、だ、tt.want) } であれば!reflect.DeepEqual(GOT1、tt.want1){ t.Errorf ( "pingCapFail()GOT1 =%V、%Vを望む"、GOT1、tt.want1) } }) } } FUNC Test_pingCapFail1(T * testing.T){ テスト:= []構造体{ 名文字列が 文字列を必要 } { {名: "pingCapFail1"、欲しい: "ユニットテスト"}、 } failpoint.Enable(「fail_point / failpoint-NAME1 」、 "リターン(5)") _、TTのために:=範囲のテスト{ t.Run(tt.name、FUNC(T * testing.T){ 得た場合:!= pingCapFail1は(); = tt.wantを{ました t.Errorf( "pingCapFail1()=%のV、%Vを望む"、得、tt.want) } }) } } Test_pingCapFail2 FUNC(T * testing.T){ 型引数構造体{ CTX context.Context } C = &gin.Context {} failPoints:=マップ[文字列]のstruct {} { "A":{}、 "B":{}、 // "fail_point / failpoint-NAME2":{} } CTX:= failpoint.WithHook(C、FUNC(CTX context.Context、fpname列)BOOL { = failPoints [fpname:実測値_、 ] //一部だけfailpointsを可能にします。 見つかっ返す }) のテストを:= []構造体{ name文字列の 引数の引数は 文字列たい failpoint.Value want1を } { { "pingCapFail2"、引数{CTX}、 "成功"、nilを}、 } failpoint .ENABLE( "fail_point / failpoint-NAME2"、 "戻る(5)") _、TT用:=レンジテスト{ {t.Run(tt.name、FUNC(T * testing.T) = pingCapFail2:得、GOT1 (tt.args.ctx) != tt.want {得た場合 t.Errorf( "pingCapFail2は、()=%vを得、%vをしたい"、tt.wantだ) } !reflect.DeepEqual(GOT1、tt.want1){もし t.Errorf(「pingCapFail2()GOT1 =%V 、」%vをしたい、GOT1、tt.want1) } }) } }
それを実行し、テスト。
私は便利になりたい、あなたに感謝します。