TextView
アクティビティにsをSave
入力し、データをデータベースにコミットするボタンのクリックをシミュレートするアプリのテストケースがあります。これを別のデータで数回繰り返し、を呼び出しInstrumentation.waitForIdleSync()
てから、挿入されたデータが実際にデータベースにあることを確認します。最近、コードを変更したり再コンパイルしたりせずに、このテストを3回続けて実行しました。結果は毎回異なりました。1回のテスト実行に合格し、他の2回のテスト実行では、データベースから欠落している異なるデータ項目が報告されました。この種の動作を引き起こす可能性があるのは何ですか?競合するスレッド間の競合状態が原因である可能性がありますか?実行するたびに結果が異なる場合、これをデバッグするにはどうすればよいですか?
3 に答える
競合状態のように見えます。スレッド化の世界では、実行時の順序を保証する方法がないことに注意してください。
私はアンドロイド開発者ではないので、推測にすぎませんが、UI は一般的に 1 つのイベント スレッド上にしかないため、別のスレッド (テスト) からメソッドを呼び出すと、イベント スレッドの外にいるため、おそらくそれを破っています。 .
セマフォまたはリソースのロックを使用してみてください。 http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html http://docs.oracle.com/javase/1.5.0/docs/api /java/util/concurrent/Semaphore.html
私は(ついに!)この問題の解決策を見つけました。ここfinish()
で、テスト対象Activity
のデータベースへの接続がすべて閉じられていることを確認します。これにより、アサーションを実行したときにデータの一貫性が確保されるようです。
データベースのデータを直接アサートするのではなく、プローブを作成することをお勧めします。これにより、x 秒 (またはアイドル時間) 待ってからチェックするのではなく、特定の時間までデータベースをチェックし続けるコードを作成することを意味します。私は適切なコンピューターを使用していないため、次のようにします。は疑似コードのみです
public static void assertDatabaseHasData(String message, String dataExpected, long maxTimeToWaitFor){
long timeToWaitUntil = System.getCurrentTimeMillis() + maxTimeToWaitFor;
boolean expectationMatched = false;
do {
if(databaseCheck() == dataExpected){
expecttionMatched == true;
}
}while(!expectationMatched && System.getCurrentTimeMillis() < timeToWaituntil);
assertTrue(message, expectationMatched);
}
コンピューターに到達したら、上記を再検討して改善しようとします(実際には、アサートするのではなくハムクレストを使用しますが、それは個人的な好みです)