0

プロジェクトのテストを作成する方法を考えています。現時点では、テスト構造は次のようになります。

RealClass 
{ 
      method1; 
      method2; 
      ...
}

そしてまったく同じテストクラス構造:

TestClass {
   testMethod1; 
   testMethod2; 
   ...
 }

しかし、私はそれが好きではありません.1つのテストメソッドにあまりにも多くのテストケースを入れているからです...

次のような構造を使用する必要があります。

TestClass {
   testMethod1Opt1; 
   testMethod1Opt2; 
   ... 
   testMethod2Opt1; 
   ...}

単体テストはどのように作成していますか?

私のテストコードの例: (非常に単純なテスト)

public void testIsAppUser() {
    // My (Artem`s Zinnatullin) uId
    final long artemZinnatullinUId = 172672179;

    try {
        assertTrue(usersApi.isAppUser(artemZinnatullinUId));
    } catch (Exception e) {
        fail(e.getMessage());
    }

    // Pavel`s Durov uId
    final long durovUId = 1;

    try {
        assertFalse(usersApi.isAppUser(durovUId));
    } catch (Exception e) {
        fail(e.getMessage());
    }

    // By default uId == current user`s (who has authorized) uId 
    try {
        assertTrue(usersApi.isAppUser(null));
    } catch (Exception e) {
        fail(e.getMessage());
    }
}

私が考えていること:

public void testIsAppUser1() {
    // My (Artem`s Zinnatullin) uId
    final long artemZinnatullinUId = 172672179;

    try {
        assertTrue(usersApi.isAppUser(artemZinnatullinUId));
    } catch (Exception e) {
        fail(e.getMessage());
    }
}

public void testIsAppUser2() {
    // Pavel`s Durov uId
    final long durovUId = 1;

    try {
        assertFalse(usersApi.isAppUser(durovUId));
    } catch (Exception e) {
        fail(e.getMessage());
    }
}

public void testIsAppUser3() {
    // By default uId == current user`s (who has authorized) uId
    try {
        assertTrue(usersApi.isAppUser(null));
    } catch (Exception e) {
        fail(e.getMessage());
    }
}

アドバイスをください。

4

4 に答える 4

2

コメント:

  1. テストメソッドtry{} catch(){ fail() }に追加するだけではありません。throws ExceptionJUnit は自動的にテストに失敗し、スタック トレースを保持します。これにより、バグ修正がはるかに簡単になります。

  2. 小さなテスト メソッドを作成します。これは名前の問題を引き起こします: たくさんの良い名前を思い付くにはどうすればよいでしょうか? ここでの解決策は、テストが呼び出すメソッドではなく、論理的にテストするものにちなんでテストに名前を付けることです。

    どのメソッドが呼び出されているかを確認したい場合は、JaCoCoなどのコード カバレッジ ツールを使用してください。

    したがって、最初のテストを呼び出す必要がありますtestIsArtemsZinnatullinAppUser()。ガイドラインとして: テストが何をするかを説明するためにコメントが必要だと感じるときはいつでも、テスト名は間違っています。コメントに書き込んだものを使用して、テスト名を作成します。

テストを小さくする必要がある理由は、JUnit が最初の問題で停止するためです。したがって、1 つのテスト ケースに 20 個のテストがあり、3 番目が失敗した場合、17 個のテストは実行されません。しかし、これらの 17 のテストには、何が問題なのかを理解するのに役立つ貴重な情報が含まれている可能性があります。

それらがすべて成功する場合、これはおそらく特定の問題です。多くのテストが失敗した場合、問題は共有コードにあるはずです。

于 2013-01-23T17:32:05.187 に答える
1

他の回答にあることは繰り返しません。しかし、これを追加するだけです:

  • テスト クラスでコード構成が重複しないようにします。
  • 明示的な失敗メッセージを書くことを躊躇しないでください。

ここに私が何を意味するかを説明するものがあります:

public void testIsAppUser1() {
    // My (Artem`s Zinnatullin) uId
    assertAppUser(172672179,true,"artemZinnatullinUId");
}

public void testIsAppUser2() {
    // Pavel`s Durov uId
    assertAppUser(1,false,"Pavel`s Durov");
}

public void testIsAppUser3() {
    // By default uId == current user`s (who has authorized) uId
    assertAppUser(null,true,"current user");
}

private void assertAppUser(Long id, boolean isExpectedAppUser, String userName){
    boolean isAppUser = usersApi.isAppUser(id);
    if(isExpectedAppUser){
        assertTrue("User with id:"+id+"and named:"+userName+" must be an appUser" ,isAppUser);
    }else{
        assertFalse("User with id:"+id+"and named:"+userName+" cannot be an appUser" ,isAppUser);
    }
}
}
于 2013-01-23T17:46:05.950 に答える
1

「例外」が原因で発生する可能性のあるエラーがある場合にのみスローします。可能であるため、必ずしもスローしないでください。以下は、独自のテスト環境を作成していることを前提としています。

あなたのアサートメソッドがどのように見えるかはわかりませんが、実際には、どちらかといえばスローする必要があります。また、例外をスローするために try catch は必要ありません。次のことができます。

throw new Exception("msg"); // Or another type of Exception

だから実装:

public void AssertEqual(Object obj1, Object obj2) throws Exception
{
    if (!obj1.equals(obj2))
        throw new Exception("Objects are not equal");
}
于 2013-01-23T17:25:12.297 に答える
1

テストを構造化する 2 番目の方法は、はるかに優れています。そうすれば、各テスト メソッドはメソッドが壊れるさまざまな方法をカバーするため、メソッドの 1 つのバグを修正してから、テストがもう少し下で失敗するというケースはありません (1 つのエラーが表示されないようにするため)。その他)。テスト メソッドがテスト対象のオブジェクトのメソッドにマップされることよりも、テスト メソッドが小さくて焦点が絞られていることがはるかに重要です。

また、例外をキャッチしないでください。JUnit がそれを行います。throws Exception各テスト メソッドのシグネチャに追加します。例外が実際にスローされたことを確認したい場合は、次のようにテストでキャッチできます。

try {
    objectUnderTest.doSomethingThatShouldThrowFooException();
    fail("should've thrown an exception before getting here");
}
catch (FooException fooEx) {
    // yay. my test passed
}

、しかし定型文:

} catch (Exception e) {
    fail(e.getMessage());
}

不要です。

于 2013-01-23T17:30:17.820 に答える