1


0

私はコントロール開発者であり、単体テストの初心者です。 ほぼ毎日、私はあなたがUIインタラクションのためにコントロールをテストすることができないという態度と戦っています。 私は、コントロールがテスト可能になるように設計されていれば手動テストを劇的に減らすことが可能であることを示すためにデモコントロールを作成しています。 現在、私は50%のロジックカバレッジを持っていますが、もっと複雑な部分をテストする方法を見つけることができれば、最大75%以上になる可能性があると思います。

たとえば、コントロールの状態を記述するプロパティを持つクラスと、いくつかのセグメントから構成されるWPFの `PathGeometry`オブジェクトを生成するメソッドがあります。 実装は次のようになります。

内部PathGeometry CreateOuterGeometry(){double arcRadius = OuterCoordinates.Radius; double sweepAngle = OuterCoordinates.SweepAngle; ArcSegment outerArc = new ArcSegment(...);

LineSegment arcEndToCenter = new LineSegment(...);

PathFigure fig = new PathFigure(); // figureを設定してセグメントを追加します...

PathGeometry outerGeometry = new PathGeometry(); outerGeometry.Figures.Add(fig); outerGeometryを返します。 }

私はこのようなカバーされていないコードの数百ブロック、余分な25%のカバレッジを説明するような他のいくつかの方法を持っています。 私はもともとこれらの方法をテストすることを計画していましたが、その概念を拒否しました。 私はまだ単体テスト初心者です、そして私がコードをテストするために考えることができる唯一の方法はこのようないくつかの方法でしょう:

void CreateOuterGeometry_AngleIsSmall_ArcSegmentIsCorrect(){ClassUnderTest classUnderTest = new ClassUnderTest();} //テスト中のクラスを設定します... ArcSegment expectedArc = //期待される円弧を生成...

PathGeometry geometry = classUnderTest.CreateOuterGeometry()ArcSegment arc = geometry.Figures.Segments [0];

Assert.AreEqual(expectedArc、arc)}

テスト自体は問題ないようです。予想されるセグメントごとに1つずつ書きます。 しかし、私はいくつかの問題を抱えていました:

  • 「最初のセグメントは `ArcSegment`ですか?」を検証するためのテストが必要ですか?理論的にはテストはこれをテストしますが、各テストは1つのことだけをテストするべきではありませんか? これは2つのことのように聞こえます。

  • コントロールには、少なくとも6つの計算ケースと4つのエッジケースがあります。これは各方法に対して少なくとも10回のテストが必要であることを意味します。

  • 開発中に、さまざまなジオメトリの生成方法が何度か変更されました。 これは私がすべてのテストを書き直さなければならない原因となります。

最初の問題は、テスト数を増やす可能性があるように思われたため、一時停止しました。 「xセグメントがありましたか」などのことをテストする必要があるかもしれないと思いました。 「セグメントnは正しい型ですか?」しかし、私はもっと考えたので、メソッドに分岐ロジックがないことを確認したので、これらのテストを一度だけ実行する必要があります。 2番目の問題は私がテストに関連した多くの努力があるだろうということをもっと確信させました。 やむを得ないようです。 3番目の問題は最初の2つを悪化させます。 ジオメトリの計算方法を変更するたびに、新しいロジックを尊重するために推定40個のテストを編集する必要があります。 これには、セグメントが追加または削除された場合のテストの追加または削除も含まれます。

これら3つの問題のために、私はコントロールを興味のある状態すべてに置き、それが特定の方法に見えるかどうかを確認するようユーザーに要求するアプリケーションと手動のテスト計画を書くことを選びました。 これは間違っていましたか? 単体テストの作成に伴う労力を過大評価していませんか。 もっと簡単かもしれないこれをテストするための代替方法はありますか? (私は現在モックとスタブを勉強しています。デザインのリファクタリングを必要とし、最終的にはほぼ同じ努力が必要になるでしょう。)

6 Answer


2


依存性注入とモックを使う。

ArcSegmentFactory、LineSegmentFactoryなどのインターフェイスを作成し、モックファクトリをクラスに渡します。 こうすることで、このオブジェクトに固有のロジックを分離することができ(テストが容易になるはずです)、他のオブジェクトのロジックには依存しなくなります。

何をテストするかについて:*あなたは*重要なものをテストする必要があります。 あなたはたぶんあなたが物事を成し遂げさせたいタイムラインを持っています、そしてあなたはたぶんすべてのことをテストすることができないでしょう。 *テストする必要があるものに優先順位を付け、優先順位の高い順にテストします(テストにかかる時間を考慮して)。 また、すでにいくつかのテストを作成したことがある場合は、他のものに対して新しいテストを作成するのがはるかに簡単になります。同じクラスに対して複数のテストを作成することに問題はありません。

変更については、それがテストの目的です。変更を許可し、変更が世界に混乱をもたらすことを本当に恐れないでください。


0


あなたは、ランダムなコントロールグラフを生成するコントロール生成ツールを書いて試してみるかもしれません。 これはあなたが考えていなかったかもしれないいくつかのデータポイントをもたらすかもしれません。


0


私たちのプロジェクトでは、厳密に言えば単体テストではないテストを実行するためにJUnitを使います。 たとえば、空のデータベースを接続し、Hibernate(Object-Relational Mappingツール)によって生成された自動スキーマをテストデータベースの実際のスキーマと比較すると便利です。これは間違ったデータベースマッピングに関する多くの問題を見つけるのに役立ちます。 しかし、一般的には…​ 与えられたテストメソッドでは、1つのクラスに対して1つのメソッドだけをテストするべきです。 それはあなたがオブジェクトのさまざまなプロパティを調べるためにそれに対して複数のアサーションを行うことができないという意味ではありません。


0


私のアプローチは、グラフを文字列(1行に1セグメント)に変換し、この文字列を期待される結果と比較することです。

コードの中で何かを変更すると、テストは失敗し始めますが、あなたがする必要があるのは失敗が正しい場所にあることを確認することだけです。 あなたのIDEはこのためにサイドバイサイドの差分を提供するべきです。

新しい出力が正しいと確信できる場合は、それを古い予想される結果の上にコピーするだけです。 これにより、間違いが気付かれずに済むことは確実になくなり(少なくとも長い間は止まりません)、テストは依然として単純であり、修正は迅速です。

次に、共通のパス部分がある場合は、それらを個々の文字列に入れて、それらの部分からテストの期待される結果を構築できます。 これはあなたが自分自身を繰り返すのを避けることを可能にします(そして共通部分が変わるなら、あなたはただすべてのテストのためにただ一つの場所を更新する必要があります)。


0


私があなたの例を正しく理解しているならば、あなたはたくさんの描画操作が与えられた結果を生むかどうかテストする方法を見つけようとしていました。

人間の目の代わりに、一連の予想されるイメージ(検証済みの「良い」イメージのスナップショット)を作成し、描画操作を使用して同じ一連のイメージを作成し、その結果をイメージ比較と比較する単体テストを作成できます。 これはあなたがグラフィック操作のテストを自動化することを可能にするでしょう、それは私があなたの問題であると理解するものです。


-1


これを行うためのテキストブックの方法は、すべてのビジネスロジックを、GUIの1行のメソッドで呼び出されるライブラリまたはコントローラに移動することです。 そうすれば、GUIを扱うことなくコントローラやライブラリを単体テストすることができます。