2010-12-14 7 views
8

私のアプリケーションを使用する際に、ユーザーがトリガーしたイベントの後にタスクを非同期で実行するために、NSOperationQueueを使用するコードで競合状態が発生しました。競合状態を解決する方法はわかっています。迷ってしまう愚かな設計ミスですが、テストケースでそのバグを証明したいと思います(最適化/リファクタリング中に戻ってこないようにしますラインを下ろす)。これは私に困ってしまった。テストの目的が競合状態を生成することである場合、マルチスレッドのテストを行うにはどうすればよいでしょうか?スレッドベースのコードをユニットテストしていますか?競合状態を強制する

スレッドや単体テストを扱う際に参考になる資料はありますか?私は特に競合状態の生成に興味があります。

+0

私は共有データ構造をモックし、あなたのモックオブジェクト内では、あなたが "間違った"順序で別のスレッドを実行させる必要がある任意の同期を行うことができます。 –

答えて

4

競合状態を引き起こす一連のイベントが実際にテスト中に発生することを確認する必要があります。そのためには、テストケース内のスレッドインターリーブに影響を与える必要があります。

追加の(条件付き)同期、または(単純で信頼性の低い)追加のタイマーを使用して、これを達成できます。いくつかのsleep()呼び出しをクリティカルセクションに入れて、他のスレッドが望ましくない状態になるのに十分長く実行されるようにします。その作業をしているときは、明示的な同期でスリープ呼び出しを置き換えます(つまり、もう一方が実際に到着したことを確認するまで、スレッドをブロックします)。

次に、テストケースで設定されたグローバルフラグを条件とします。

+3

私は正直なところ、この特定のテストに実際の生産コードを強く結び付けることは良い考えではないと思います。つまり、コードをリファクタリングするたびにこの結合を動かさないように注意する必要があります。これは、最初にこのテストを受ける点を打ち破ります。 –

+0

いいえ、脆弱性wrt。リファクタリングは実際にこのテスト手法をサポートしています。あなたがリファクタリングするときは、競争条件を再考する必要があります。そして、リファクタリングが実際に新しいものを導入したこと、またはこれまでに脆弱だったものがもう起こり得ないことがわかります。 –

+0

私は、これが潜在的な競合状態を再考するためにどのようにリファクタリングを "強制"するのか、そうすることが実際には有用であるか分かりません。明らかに、競争状態を考えることは初めてではありませんでした。コードを任意の重要な程度までリファクタリングすると、既存のテストコードをすべて投げ捨てて新しいコードを書き込むか、テストコードを役に立たなくする必要があります。いずれにしても、テストコードを取得する目的は敗北します。メインコードベースを汚染しないテストコードを持つことが良いでしょうが、そうであればビルドにフラグを立てます。 –

関連する問題