2017-04-04 15 views
2

Goの不透明でないエラー値を比較するためのベストプラクティスはありますか?不透明でないエラー値のテスト

ほとんどのコードベースは、エラーを不透明なものとして扱います(操作が成功したか失敗したか、エラーの原因に関する内部の詳細は表示されません)。

これにより、ユニットテストを簡単に作成できます。これは、予想されるエラーに対して実際のエラーをアサートするだけでよいからです。私が人々にしたことのほとんどは、エラー文字列を比較して、少なくともいくつかの重要な情報が含まれていることを確認することです。たとえば、次のように

if err == nil || !strings.Contains(err.Error(), "not found in the Raft configuration") { 
    t.Fatalf("err: %v", err) 
} 

しかし、(無効なフィールド名、値、エラーコードとおそらくいくつかのネストされたエラーすぎを指定する必要がフォーム検証のように)追加のエラー情報が必要な場合のために

、どのようなあなたはしますか?

私は単純にreflect.DeepEqual()を実行することはできません。エラーには毎回比較が失敗するユニークなスタックトレースが含まれているためです。また、ネストされたエラーがあると、テストロジックがさらに複雑になり、必要なフィールドを比較するためにあらゆる種類のエラーが発生しやすいロジック(ループ、再帰)が必要になります。この性質のエラーをテストする標準的な方法はありますか?

+1

あなたは彼らが設定されたことを確認するために自分の存在を確認することができ、「決定論的」ではありませんこれらの値は、その後、彼らのゼロ値( '「」'、 'nil'などにそれらを設定します)残りを 'reflect.DeepEqual'に渡します。理想的ではありませんが、機能します。 – mkopriva

答えて

1

正しい方法で行われていないエラーのチェックに関する質問には答えられないかもしれませんが、ここでは正しい方法でエラーを作成して使用する方法の例を示します。

一般的に標準ライブラリパッケージで行われていることは、エクスポートされた変数としてエラーが作成され、それらをスローして比較することができます。ここに例があります...それは想像を絶するかもしれませんが。

https://play.golang.org/p/JlpguFn2NX

package main 

import (
    "errors" 
    "fmt" 
) 

var ErrBadIdea = errors.New("that was dumb") 
var ErrNoValue = errors.New("not a real value") 

func DoSomething(i int) error { 
    if i == 0 { 
     return ErrNoValue 
    } 
    if i < 0 { 
     return ErrBadIdea 
    } 
    // does something that doesn't like negative or zero values 
    return nil 
} 

func main() { 
    err := DoSomething(-1) 
    fmt.Println(err == ErrBadIdea, err) 
    err = DoSomething(0) 
    fmt.Println(err == ErrNoValue, err) 
} 

本の優れた例は、標準ライブラリのdatabase/sqlパッケージです。

https://godoc.org/database/sql#pkg-variables

これらの変数はそうあなたがそう

if err == sql.ErrNoRows { // these are not the rows you are looking for } 

それが良くなるようにテストすることができますが存在します!

errorinterfaceなので実装するだけです。あなただけが必要なのはfunc Error() stringです。次の例を参照して、interfaceの威力で驚嘆してください。

https://play.golang.org/p/3RFrxKGkdm

はまた、エラーに関する次のブログを読んでください。

https://blog.golang.org/error-handling-and-go

+0

質問を見てくれてありがとう。私はこのタイプのカスタムエラーに関してあなたが「正しくない」と考えるものについて興味があります。単純なエラー文字列よりも多くのコンテキストを必要とするエラーが発生した場合は、どのような方法がありますか?上記の例のように、特定のエラーコードと失敗の理由を返すJSONエンドポイントがある場合。これは単なるエラー変数でどのように達成できますか? – user7467314

+0

問題は人々がコード化して「これはエラーケースです」と判断しているので、もし何か{return errors.New( "bad")} 'と遅延してしまいます。その後、彼らは大衆が使うために図書室に図書館を掲示します。しかし、返されたエラーは完全に役に立たず、何かが間違っているとしか伝えません。問題はその後伝播し、人々はこれを続け、今では価値のないエラーの欠点が返されています。また、 'Error()'インタフェースを実装すればよいので、より有用なエラーを返すことができます。私は例で私の答えを更新します。 – RayfenWindspear

+0

これらの無駄なエラーに対処するためには、おそらく文字列にマッチさせるだけで、それを投げたライブラリが文言を変更することを望んでいないと願っています。 – RayfenWindspear

関連する問題