it-swarm-id.com

Eksekusi sebelum dan Setelah Suite kait di jUnit 4.x

Saya mencoba melakukan preform pengaturan dan teardown untuk satu set tes integrasi, menggunakan jUnit 4.4 untuk menjalankan tes. Teardown harus dijalankan dengan andal. Saya mengalami masalah lain dengan TestNG, jadi saya ingin port kembali ke jUnit. Kait apa yang tersedia untuk dieksekusi sebelum tes dijalankan dan setelah semua tes selesai?

Catatan: kami menggunakan maven 2 untuk bangunan kami. Saya sudah mencoba menggunakan maven's pre- & post-integration-test fase, tetapi, jika tes gagal, pakar berhenti dan tidak berjalan post-integration-test, yang tidak membantu.

81
sblundy

Ya, adalah mungkin untuk menjalankan metode pengaturan dan penghancuran yang andal sebelum dan sesudah pengujian apa pun di suite pengujian. Biarkan saya menunjukkan dalam kode:

package com.test;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({Test1.class, Test2.class})
public class TestSuite {

    @BeforeClass
    public static void setUp() {
        System.out.println("setting up");
    }

    @AfterClass
    public static void tearDown() {
        System.out.println("tearing down");
    }

}

Jadi kelas Test1 Anda akan terlihat seperti:

package com.test;

import org.junit.Test;


public class Test1 {
    @Test
    public void test1() {
        System.out.println("test1");
    }

}

... dan Anda dapat membayangkan bahwa Test2 terlihat mirip. Jika Anda menjalankan TestSuite, Anda akan mendapatkan:

setting up
test1
test2
tearing down

Jadi, Anda dapat melihat bahwa pengaturan/penghancuran hanya berjalan sebelum dan sesudah semua pengujian, masing-masing.

Tangkapan: ini hanya berfungsi jika Anda menjalankan test suite, dan tidak menjalankan Test1 dan Test2 sebagai tes JUnit individual. Anda menyebutkan bahwa Anda menggunakan maven, dan plugin maven pasti suka menjalankan tes satu per satu, dan bukan bagian dari suite. Dalam hal ini, saya akan merekomendasikan membuat superclass yang diperluas setiap kelas tes. Superclass kemudian berisi metode @BeforeClass dan @AfterClass beranotasi. Meskipun tidak sebersih metode di atas, saya pikir itu akan berhasil untuk Anda.

Sedangkan untuk masalah dengan tes gagal, Anda dapat mengatur maven.test.error.ignore sehingga build berlanjut pada tes yang gagal. Ini tidak direkomendasikan sebagai praktik yang berkelanjutan, tetapi harus membuat Anda berfungsi sampai semua tes Anda berlalu. Untuk detail lebih lanjut, lihat dokumentasi maven surefire .

111
Julie

Seorang kolega saya menyarankan yang berikut ini: Anda dapat menggunakan RunListener khusus dan menerapkan metode testRunFinished (): http://junit.sourceforge.net/javadoc/org/junit/runner/notification/RunListener.html# testRunFinished (org.junit.runner.Result)

Untuk mendaftarkan RunListener, cukup konfigurasikan plugin surefire sebagai berikut: http://maven.Apache.org/surefire/maven-surefire-plugin/examples/junit.html bagian "Menggunakan pendengar dan reporter khusus"

Konfigurasi ini juga harus dipilih oleh plugin failafe. Solusi ini sangat bagus karena Anda tidak harus menentukan Suites, mencari kelas tes atau hal-hal ini - itu memungkinkan Maven untuk melakukan keajaibannya, menunggu semua tes selesai.

32
Martin Vysny
11
Tobogganski

Menggunakan anotasi, Anda dapat melakukan sesuatu seperti ini:

import org.junit.*;
import static org.junit.Assert.*;
import Java.util.*;

class SomethingUnitTest {
    @BeforeClass
    public static void runBeforeClass()
    {

    }

    @AfterClass
    public static void runAfterClass()
    {  

    }

    @Before  
    public void setUp()
    {

    }

    @After
    public void tearDown()
    {

    }

    @Test
    public void testSomethingOrOther()
    {

    }

}
7
Jroc

Disini kita

  • ditingkatkan ke JUnit 4.5,
  • menulis anotasi untuk menandai setiap kelas uji atau metode yang membutuhkan layanan yang berfungsi,
  • menulis penangan untuk setiap penjelasan yang berisi metode statis untuk mengimplementasikan pengaturan dan penghancuran layanan,
  • memperluas Runner biasa untuk menemukan anotasi pada tes, menambahkan metode pengendali statis ke dalam rantai eksekusi tes pada titik yang sesuai.
3
carym

Asalkan semua tes Anda dapat memperpanjang kelas "teknis" dan berada dalam paket yang sama, Anda dapat melakukan sedikit trik:

public class AbstractTest {
  private static int nbTests = listClassesIn(<package>).size();
  private static int curTest = 0;

  @BeforeClass
  public static void incCurTest() { curTest++; }

  @AfterClass
  public static void closeTestSuite() {
      if (curTest == nbTests) { /*cleaning*/ }             
  }
}

public class Test1 extends AbstractTest {
   @Test
   public void check() {}
}
public class Test2 extends AbstractTest {
   @Test
   public void check() {}
}

Perlu diketahui bahwa solusi ini memiliki banyak kelemahan:

  • harus menjalankan semua tes paket
  • harus subkelas kelas "techincal"
  • anda tidak dapat menggunakan @BeforeClass dan @AfterClass di dalam subkelas
  • jika Anda hanya menjalankan satu tes dalam paket, pembersihan tidak dilakukan
  • ...

Untuk informasi: listClassesIn () => Bagaimana Anda menemukan semua subclass dari kelas yang diberikan di Jawa?

2
christophe blin

Adapun "Catatan: kami menggunakan maven 2 untuk bangunan kami. Saya sudah mencoba menggunakan fase pra-& pasca-integrasi-uji pakar, tetapi, jika tes gagal, pakar berhenti dan tidak menjalankan uji pasca-integrasi , yang tidak membantu. "

anda dapat mencoba gagal-plugin sebagai gantinya, saya pikir itu memiliki fasilitas untuk memastikan pembersihan terjadi terlepas dari pengaturan atau status tahap menengah

2
Binod Pant

Jika Anda tidak ingin membuat suite dan harus membuat daftar semua kelas tes Anda, Anda dapat menggunakan refleksi untuk menemukan jumlah kelas tes secara dinamis dan menghitung mundur dalam kelas dasar @AfterClass untuk melakukan tearDown hanya sekali:

public class BaseTestClass
{
    private static int testClassToRun = 0;

    // Counting the classes to run so that we can do the tear down only once
    static {
        try {
            Field field = ClassLoader.class.getDeclaredField("classes");
            field.setAccessible(true);

            @SuppressWarnings({ "unchecked", "rawtypes" })
            Vector<Class> classes = (Vector<Class>) field.get(BlockJUnit4ClassRunner.class.getClassLoader());
            for (Class<?> clazz : classes) {
                if (clazz.getName().endsWith("Test")) {
                    testClassToRun++;
                }
            }
        } catch (Exception ignore) {
        }
    }

    // Setup that needs to be done only once
    static {
        // one time set up
    }

    @AfterClass
    public static void baseTearDown() throws Exception
    {
        if (--testClassToRun == 0) {
            // one time clean up
        }
    }
}

Jika Anda lebih suka menggunakan @BeforeClass daripada blok statis, Anda juga dapat menggunakan bendera boolean untuk melakukan penghitungan refleksi dan menguji pengaturan hanya sekali pada panggilan pertama. Semoga ini bisa membantu seseorang, butuh satu sore untuk mencari cara yang lebih baik daripada menghitung semua kelas dalam sebuah suite.

Sekarang yang perlu Anda lakukan adalah memperluas kelas ini untuk semua kelas tes Anda. Kami sudah memiliki kelas dasar untuk menyediakan beberapa hal umum untuk semua tes kami jadi ini adalah solusi terbaik bagi kami.

Inspirasi berasal dari ini SO jawaban https://stackoverflow.com/a/37488620/5930242

Jika Anda tidak ingin memperpanjang kelas ini di mana-mana, jawaban SO terakhir ini mungkin sesuai keinginan Anda).

0
FredBoutin

Karena maven-surefire-plugin tidak menjalankan kelas Suite terlebih dahulu tetapi memperlakukan suite dan kelas uji sama, jadi kami dapat mengonfigurasi plugin seperti di bawah ini untuk mengaktifkan hanya kelas suite dan menonaktifkan semua tes. Suite akan menjalankan semua tes.

        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.5</version>
            <configuration>
                <includes>
                    <include>**/*Suite.Java</include>
                </includes>
                <excludes>
                    <exclude>**/*Test.Java</exclude>
                    <exclude>**/*Tests.Java</exclude>
                </excludes>
            </configuration>
        </plugin>
0
Anurag Sharma

Satu-satunya cara saya berpikir kemudian untuk mendapatkan fungsionalitas yang Anda inginkan adalah melakukan sesuatu seperti

import junit.framework.Test;  
import junit.framework.TestResult;  
import junit.framework.TestSuite;  

public class AllTests {  
    public static Test suite() {  
        TestSuite suite = new TestSuite("TestEverything");  
        //$JUnit-BEGIN$  
        suite.addTestSuite(TestOne.class);  
        suite.addTestSuite(TestTwo.class);  
        suite.addTestSuite(TestThree.class);  
        //$JUnit-END$  
     }  

     public static void main(String[] args)  
     {  
        AllTests test = new AllTests();  
        Test testCase = test.suite();  
        TestResult result = new TestResult();  
        setUp();  
        testCase.run(result);  
        tearDown();  
     }  
     public void setUp() {}  
     public void tearDown() {}  
} 

Saya menggunakan sesuatu seperti ini di Eclipse, jadi saya tidak yakin seberapa portabel itu di luar lingkungan itu

0
Jroc

Sejauh yang saya tahu tidak ada mekanisme untuk melakukan ini di JUnit, namun Anda dapat mencoba mensubklasifikasikan Suite dan mengganti metode run () dengan versi yang menyediakan kait.

0
user15299