Fortsetzen der Testausführung in junit4, selbst wenn eine der Assertionen fehlschlägt

Lesezeit: 6 Minuten

Benutzer-Avatar
Benutzer85

Ich habe mein vorhandenes Framework mit Jfunc aufgebaut, das eine Möglichkeit bietet, die Ausführung fortzusetzen, selbst wenn einer der Asserts im Testfall fehlschlägt. Jfunc verwendet das Junit 3.x-Framework. Aber jetzt migrieren wir auf junit4, sodass ich Jfunc nicht mehr verwenden kann und es durch junit 4.10 jar ersetzt habe.
Das Problem besteht nun darin, dass wir jfunc in unserem Framework ausgiebig verwendet haben und mit junit 4 unseren Code dazu bringen wollen, die Ausführung fortzusetzen, selbst wenn eines der Asserts in einem Testfall fehlschlägt.
Hat jemand einen Vorschlag/eine Idee dafür, ich weiß im Juni, dass die Tests atomarer sein müssen, dh eine Bestätigung pro Testfall, aber wir können das aus irgendeinem Grund in unserem Framework nicht tun.

Benutzer-Avatar
Chris B

Sie können dies mit einem tun ErrorCollector Regel.

Um sie zu verwenden, fügen Sie zuerst die Regel als Feld in Ihrer Testklasse hinzu:

public class MyTest {
    @Rule
    public ErrorCollector collector = new ErrorCollector();

    //...tests...
}

Ersetzen Sie dann Ihre Asserts durch Aufrufe von collector.checkThat(...).

z.B

@Test
public void myTest() {
    collector.checkThat("a", equalTo("b"));
    collector.checkThat(1, equalTo(2));
}

  • Danke für die Antwort Chris. Es funktionierte und wurde nach dem ersten Fehler fortgesetzt (dh collect.checkThat(10, CoreMatchers.equalTo(11))). Aber das Problem ist, dass ich möchte, dass der Test als fehlgeschlagen markiert wird, selbst wenn eine der Prüfungen fehlschlägt. Derzeit wird der Test nach Ausführung des obigen Tests als bestanden markiert. Ich möchte, dass es fehlschlägt und den Stacktrace in der Fehlerzeile anzeigt (ähnlich wie wenn eine Assertion fehlschlägt).

    – Benutzer85

    19. April 2012 um 7:57 Uhr


  • Das ist merkwürdig. Ich habe gerade den Code ausprobiert, den ich in meiner Antwort geschrieben habe, und er hat wie erwartet funktioniert. Der Test schlägt fehl und druckt den Stack-Trace jeder fehlgeschlagenen Behauptung aus. Hier ist der vollständige Testcode und die Ausgabe, die ich beim Ausführen des Tests von IntelliJ erhalten habe: gist.github.com/2419626

    – Chris B

    19. April 2012 um 8:24 Uhr

  • Oh … schade, ich habe nur vergessen, die Regel hinzuzufügen, und das hat das ganze Chaos verursacht … Entschuldigung für die Verwirrung und vielen Dank für den Beitrag.

    – Benutzer85

    19. April 2012 um 9:17 Uhr

  • Nur zu Ihrer Information, Sie können eine Nachricht an die anhängen checkThat -Methode, indem Sie einfach einen String als ersten Parameter hinzufügen. Diese Methode wird jedoch erst nach 4.10 (einschließlich) unterstützt..

    – Nier

    16. Mai 2016 um 7:20 Uhr


  • Hallo, werden alle fehlgeschlagenen Schritte auch als „Fehlgeschlagen“ markiert?

    – Sakshi Singla

    24. September 2019 um 6:53 Uhr

Benutzer-Avatar
Status Quo

Ich verwende auch den ErrorCollector, verwende aber auch assertThat und platziere sie in einem Try-Catch-Block.

import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;

@Rule
public ErrorCollector collector = new ErrorCollector();

@Test
public void calculatedValueShouldEqualExpected() {
    try {
        assertThat(calculatedValue(), is(expected));
    } catch (Throwable t) {
        collector.addError
        // do something
    }
}

Benutzer-Avatar
Mark

Sie können auch verwenden assertj – weiche Behauptung

@Test
public void testCollectErrors(){
   SoftAssertions softly = new SoftAssertions();
   softly.assertThat(true).isFalse();
   softly.assertThat(false).isTrue();
   // Don't forget to call SoftAssertions global verification !
   softly.assertAll();
}

Es gibt auch andere Möglichkeiten, es zu verwenden, ohne softly.assertAll();

  1. mit Regel
  2. mit automatischem Verschluss
  3. Verwenden der statischenasserSoftly-Methode

  • Da dies ohne try…catch und wie von den lib-Autoren beabsichtigt funktioniert, halte ich dies für die kanonischste Lösung.

    – Nils-o-mat

    21. Dezember 2021 um 12:19 Uhr

Benutzer-Avatar
AAA

Verwenden Sie try/finally-Blöcke. Das hat in meinem Fall funktioniert:

...
try {
    assert(...)
} finally {
    // code to be executed after assert
}
...

Try – catch, in “try” die Assertion verwenden, in “catch” den möglichen Fehler zur Sammlung hinzufügen. Lösen Sie dann die Ausnahme am Ende des Tests in tearDown() aus. Wenn es also einen Fehler/Fehler beim Assertion gibt, wird es abgefangen und der Test wird fortgesetzt. (Die Sammlung im Beispiel ist statisch, Sie können auch für jeden @Test eine neue Instanz in setUp() erstellen.)

    public static List<String> errors = new ArrayList<>();


    try {
        //some assert...
    }
    catch (AssertionError error) {
        errors.add(error.toString());
    }



    @After
    public void tearDown() {

        try {
            if (!errors.isEmpty()) {
                throw new AssertionError(errors);
            }
        }
        finally {
            //empty list because it's static, alternatively make instance for each test in setUp()
            errors.clear();
        }
    }

Benutzer-Avatar
Dimitri Algasin

Ich habe meine eigene Klasse für einfache Behauptungen erstellt. Einfach mit Ihren Anwendungsfällen zu erweitern:

public class MyEquals {

public static void checkTestSummary(MyTestSummary myTestSummary) {
    final List<MyTestResult> conditions = myTestSummary.getTestResults();
    final int total = conditions.size();

    final boolean isSuccessful = myTestSummary.isSuccessful();
    if (isSuccessful) {
        System.out.println(format("All [%s] conditions are successful!", total));
    } else {
        final List<MyTestResult> failedConditions = conditions.stream().filter(MyTestResult::isTestResult).collect(Collectors.toList());
        System.out.println(format("\nNot yet.. [%s out of %s] conditions are failed", failedConditions.size(), total));
    }

    if (!isSuccessful) {
        for (int i = 0; i < total; i++) {
            final MyTestResult myTestResult = conditions.get(i);
            if (myTestResult.isTestResult()) {
                System.out.println(format("  Success [%s of %s] => Expected %s Actual %s Good!", i + 1, total, myTestResult.getExpected(), myTestResult.getActual()));
            } else {
                System.out.println(format("!! Failed [%s of %s] => Expected %s Actual %s", i + 1, total, myTestResult.getExpected(), myTestResult.getActual()));
            }
        }
    }

    assertTrue(isSuccessful);
}

public static void myAssertEquals(MyTestSummary myTestSummary, Object expected, Object actual) {
    if (checkEquals(expected, actual)) {
        assertEquals(expected, actual);
        myTestSummary.addSuccessfulResult(expected, actual);
    } else {
        myTestSummary.addFailedResult(expected, actual);
        myTestSummary.setSuccessful(false);
    }
}

public static boolean checkEquals(Object value1, Object value2) {
    if (value1 == null && value2 == null) {
        return true;
    } else if (value1 != null && value2 == null) {
        return false;
    } else if (value1 == null && value2 != null) {
        return false;
    } else if (value1 != null && value2 != null) {
        return value1.equals(value2);
    }
    return false;
}

}

@Builder
@Value
public class MyTestResult {

    String expected;

    String actual;

    boolean testResult;

 }



@Data
public class MyTestSummary {

private boolean successful = true;

private List<MyTestResult> testResults = new ArrayList<>();

public MyTestSummary() {
}

public void addSuccessfulResult(Object expected, Object actual) {
    getTestResults().add(MyTestResult.builder()
        .expected(String.valueOf(expected))
        .actual(String.valueOf(actual))
        .testResult(true)
        .build()
    );
}

public void addFailedResult(Object expected, Object actual) {
    getTestResults().add(MyTestResult.builder()
        .expected(String.valueOf(expected))
        .actual(String.valueOf(actual))
        .testResult(false)
        .build()
    );
}
}

Verwendung im Junit-Test

@Test
public void testThat() {
    MyTestSummary myTestSummary = new MyTestSummary();
    myAssertEquals(myTestSummary, 10, 5 + 5);
    myAssertEquals(myTestSummary, "xxx", "x" + "x");
    checkTestSummary(myTestSummary);
}

Ausgabe:

Not yet.. [1 out of 2] conditions are failed
Success [1 of 2] => Expected 10 Actual 10 Good!
!! Failed [2 of 2] => Expected xxx Actual xx

 org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
 Expected :true
 Actual   :false

Benutzer-Avatar
Georgios Syngouroglou

Eine weitere Option ist das beobachtbare Muster in Verbindung mit Lambda-Ausdrücken. Sie können so etwas wie das obige verwenden.

public class MyTestClass {

    private final List<Consumer<MyTestClass>> AFTER_EVENT = new ArrayList<>();

    @After
    public void tearDown() {
        AFTER_EVENT.stream().forEach(c -> c.accept(this));
    }

    @Test
    public void testCase() {
        //=> Arrange
        AFTER_EVENT.add((o) -> {
            // do something after an assertion fail.
        }));

        //=> Act

        //=> Assert
        Assert.assertTrue(false);
    }
}

1054130cookie-checkFortsetzen der Testausführung in junit4, selbst wenn eine der Assertionen fehlschlägt

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy