Mengabaikan tes pada JUnit 4

365

OK, jadi @Ignorepenjelasannya bagus untuk menandai bahwa test case tidak boleh dijalankan.

Namun, terkadang saya ingin mengabaikan tes berdasarkan informasi runtime. Contohnya adalah jika saya memiliki tes konkurensi yang perlu dijalankan pada mesin dengan sejumlah inti. Jika tes ini dijalankan pada mesin uniprocessor, saya tidak berpikir itu benar untuk hanya lulus tes (karena belum dijalankan), dan tentu saja tidak akan benar untuk gagal dalam tes dan merusak build .

Jadi saya ingin dapat mengabaikan tes saat runtime, karena ini sepertinya hasil yang tepat (karena kerangka uji akan memungkinkan build untuk lulus tetapi catat bahwa tes tidak berjalan). Saya cukup yakin bahwa anotasi tidak akan memberikan saya fleksibilitas ini, dan curiga bahwa saya perlu membuat test suite secara manual untuk kelas yang bersangkutan. Namun, dokumentasi tidak menyebutkan apa-apa tentang ini dan melihat melalui API juga tidak jelas bagaimana hal ini akan dilakukan secara terprogram (yaitu bagaimana saya membuat program secara terprogram Testatau serupa yang setara dengan yang dibuat oleh @Ignoreanotasi?).

Jika ada yang pernah melakukan hal serupa di masa lalu, atau memiliki ide cemerlang tentang bagaimana lagi saya bisa melakukan ini, saya akan senang mendengarnya.

Andrzej Doyle
sumber

Jawaban:

476

Cara JUnit adalah melakukan ini pada saat run-time org.junit.Assume.

 @Before
 public void beforeMethod() {
     org.junit.Assume.assumeTrue(someCondition());
     // rest of setup.
 }

Anda dapat melakukannya dalam suatu @Beforemetode atau dalam tes itu sendiri, tetapi tidak dalam suatu @Aftermetode. Jika Anda melakukannya dalam tes itu sendiri, @Beforemetode Anda akan dijalankan. Anda juga dapat melakukannya di dalam @BeforeClassuntuk mencegah inisialisasi kelas.

Kegagalan asumsi menyebabkan tes diabaikan.

Sunting: Untuk membandingkan dengan @RunIfanotasi dari junit-ext , kode sampel mereka akan terlihat seperti ini:

@Test
public void calculateTotalSalary() {
    assumeThat(Database.connect(), is(notNull()));
    //test code below.
}

Belum lagi bahwa lebih mudah untuk menangkap dan menggunakan koneksi dari Database.connect()metode dengan cara ini.

Yishai
sumber
1
@tidak, itu bukan pengamatan saya sama sekali. Mereka diabaikan. Pelari uji IDEA melaporkannya seperti itu, dan melihat kode sumber JUnit menunjukkan bahwa itu melaporkan tes tersebut diabaikan.
Yishai
1
Mengutip: "Di masa depan, ini mungkin berubah, dan asumsi yang gagal dapat menyebabkan tes diabaikan." Itu sebenarnya berubah, pada 4,5 saya percaya. Javadoc saat ini mengatakan: "Runner JUnit default memperlakukan tes dengan asumsi gagal sebagai diabaikan. Runner kustom mungkin berperilaku berbeda." github.com/KentBeck/junit/blob/…
Yishai
4
Eclipse 3.6 dengan Junit 4.8.1 melaporkan Asumsi palsu sebagai tes kelulusan. Sama dengan semut 1.8.1.
fijiaaron
8
Bahwa Eclipse melaporkan asumsi yang gagal sebagai passing adalah bug: bugs.eclipse.org/bugs/show_bug.cgi?id=359944
Martin
1
@ JeffStorey, maka Anda mencari beberapa hal. Salah satunya adalah @BeforeClassanotasi, di mana Anda dapat membuat asumsi Anda gagal di sana, yang akan melewati seluruh kelas. Lain adalah @ClassRule(untuk kontrol berbutir halus, tetapi seluruh kelas, satu kali).
Yishai
51

Anda harus checkout Junit-extproyek. Mereka memiliki RunIfanotasi yang melakukan tes bersyarat, seperti:

@Test
@RunIf(DatabaseIsConnected.class)
public void calculateTotalSalary() {
    //your code there
}

class DatabaseIsConnected implements Checker {
   public boolean satisify() {
        return Database.connect() != null;
   }
}

[Contoh kode diambil dari tutorial mereka]

tidak ada
sumber
3
Terima kasih atas jawaban ini - sintaks alternatif yang menarik untuk fungsi ini, meskipun saya akan Assumelangsung menggunakannya agar tidak memperkenalkan ketergantungan lain.
Andrzej Doyle
3
Saya pribadi lebih suka solusi ini. Jika Anda memiliki banyak tes yang harus dijalankan berdasarkan kondisi yang sama, ini akan jauh lebih ideal daripada harus menggunakan Asumsikan dalam setiap tes. Juga, jika ini dapat digunakan pada tingkat kelas daripada tingkat metode, itu akan menjadi lebih ideal.
Richard
Saya lebih suka, karena ini membantu menjalankan tes bersyarat pada waktu berjalan. Cocok di mana sejumlah unit test akan dijalankan dan persyaratannya adalah untuk menjalankan tes unit pada pemeriksa tertentu. Saya benar-benar kagum melihat bahwa junit-ext tidak tersedia di repositori maven. Bagaimana kita dapat memanfaatkan ini dalam proyek pakar.
shambhu
4
Anotasi seperti @RunIfmemisahkan kondisi saat tes harus dijalankan dari kode tes yang sebenarnya, yang menurut saya bagus. Yang tidak saya sukai adalah itu membutuhkan pelari ujian khusus. Oleh karena itu saya menulis aturan JUnit untuk mengabaikan tes secara kondisional.
Rüdiger Herrmann
2
Setelah memasang tabung junit-ext (ditemukan di sini code.google.com/p/junit-ext/downloads/… ) di repositori lokal kami dan menerapkan anotasi @RunIf ini ... tidak ada! Itu benar-benar diabaikan, dan saya pikir alasannya mungkin karena junit-ext tampaknya bergantung pada junit 4.5. Kami membutuhkan 4.9+ karena uji pegas. Jadi ... tidak apa-apa.
Marc
7

Di JUnit 4, opsi lain untuk Anda mungkin adalah membuat anotasi untuk menyatakan bahwa tes tersebut harus memenuhi kriteria khusus Anda, lalu perpanjang pelari default dengan milik Anda sendiri dan menggunakan refleksi, buat keputusan berdasarkan kriteria khusus. Mungkin terlihat seperti ini:

public class CustomRunner extends BlockJUnit4ClassRunner {
    public CTRunner(Class<?> klass) throws initializationError {
        super(klass);
    }

    @Override
    protected boolean isIgnored(FrameworkMethod child) {
        if(shouldIgnore()) {
            return true;
        }
        return super.isIgnored(child);
    }

    private boolean shouldIgnore(class) {
        /* some custom criteria */
    }
}
Kyle Shrader
sumber
Walaupun ini terlihat bagus dan bersih, itu tidak berfungsi dengan versi saat ini jika JUnit4, karena BlockJUnit4ClassRunnertidak menawarkan isIgnoredmetode lagi.
Dave
-2

Catatan singkat: Assume.assumeTrue(condition)mengabaikan langkah-langkah selanjutnya tetapi lulus ujian. Untuk gagal tes, gunakan org.junit.Assert.fail()di dalam pernyataan bersyarat. Bekerja sama seperti Assume.assumeTrue()tetapi gagal tes.

TIN TIN
sumber
5
Sebagaimana dicatat dalam jawaban di atas, asumsi gagal tidak menyebabkan tes lulus, itu mengembalikan status terpisah. Beberapa pelari mungkin keliru melaporkan ini seolah-olah lulus, tapi itu kelemahan / bug dalam pelari uji (dan pelari JUnit default menampilkan tes sebagai diabaikan). Dan untuk kalimat terakhir Anda, gagal dalam ujian secara khusus bukan yang ingin saya lakukan.
Andrzej Doyle
Oh oke. Tes lulus pada asumsi gagal dalam kasus saya, tetapi saya ingin mereka dilaporkan gagal (saya sedang memeriksa pengecualian dari Test Watcher). Memaksa kegagalan membantu saya.
BERLIHAT DALAM