Junit4: Kasus uji yang terputus menyebabkan kegagalan acak dengan penggunaan kembali utas

Dibuat pada 28 Sep 2016  ·  14Komentar  ·  Sumber: junit-team/junit4

Setiap kali kasus uji terputus (Thread.interrupt()), utas uji coba tampaknya tetap dalam status terputus. Ini menyebabkan kegagalan acak nanti ketika utas digunakan kembali untuk kasus uji lainnya.

Perilaku yang diharapkan: Saat utas digunakan kembali, bendera yang terputus untuk utas dibersihkan sebelum memulai kasus uji baru. Ini dapat dilakukan dengan memanggil Thread.interrupted() , yang mengembalikan status yang terputus, dan menghapus tanda yang terputus.

Kode berikut harus mereproduksi masalah, mengingat test1 dijalankan sebelum test2

import org.junit.Test;

public class ThreadTest {
  <strong i="9">@Test</strong>
  public void test1() {
    Thread.currentThread().interrupt();
  }

  <strong i="10">@Test</strong>
  public void test2() throws InterruptedException {
    Thread.sleep(1000);
  }
}

Masalah yang saya temui mirip dengan yang dijelaskan di https://www.thoughtwire.com/junit-interupt/

bug

Komentar yang paling membantu

Saya akan mendukung gagasan untuk memanggil Thread.interrupted() pada setiap utas yang digunakan kembali untuk lebih dari satu kasus uji sebelum menjalankan kasus uji baru. Tetapi terutama jika satu utas digunakan untuk lebih dari satu kelas tes. Bendera yang terputus adalah status yang bocor dari satu kasus uji ke kasus lain, membuat kasus uji terkelupas. Terutama kasus uji yang berhubungan dengan banyak utas yang terkenal sulit untuk diperbaiki.

Semua 14 komentar

Terima kasih atas laporan bugnya.

Saya ingin tahu apakah JUnit harus menyebabkan tes yang lulus gagal jika bit yang terputus disetel selama uji coba. Saya kira tidak, karena begitu banyak tes yang lulus akan mulai gagal, dan perbaikannya adalah dengan memercikkan panggilan interrupted() mana-mana.

Ada juga pertanyaan apakah ExpectesException assertThrows() atau expectThrows() harus menghapus bit yang terputus. Saya menduga mereka harus.

@junit-team/junit-committers pemikiran?

Saya akan mendukung gagasan untuk memanggil Thread.interrupted() pada setiap utas yang digunakan kembali untuk lebih dari satu kasus uji sebelum menjalankan kasus uji baru. Tetapi terutama jika satu utas digunakan untuk lebih dari satu kelas tes. Bendera yang terputus adalah status yang bocor dari satu kasus uji ke kasus lain, membuat kasus uji terkelupas. Terutama kasus uji yang berhubungan dengan banyak utas yang terkenal sulit untuk diperbaiki.

@kcooney saya bisa mulai mengerjakan ini.

@npathai fantastis!

Masih ada pertanyaan terbuka apakah ExpectedException atau assertThrows() harus menghapus bit yang terputus. @junit-team/junit-committers pemikiran?

IMHO kita harus menghapus flag yang terputus setelah setiap tes. Kita tidak boleh menghapusnya di ExpectedException dan assertThrows() karena akan dihapus setelah pengujian.

@kcooney dapatkah Anda menjelaskan mengapa Anda berpikir bahwa ExpectedException dan assertThrows() harus menghapus bendera.

@stefanbirkner panduan umum yang saya baca adalah setiap kali Anda menangkap InterruptedException dan tidak mengulanginya, Anda harus menelepon interrupt (lihat https://www.ibm.com/developerworks/library /j-jtp05236/index.html dan cari "Jangan telan interupsi"). Sejak ExpectedException dan assertThrows() "menelan" pengecualian tak terduga, saya ingin melihat apa yang menurut orang harus kita lakukan.

FWIW, saya melakukan pencarian cepat di GitHub untuk panggilan ke interrupted() di JUnit 5 dan saya tidak menemukan panggilan apa pun.

@kcooney @stefanbirkner Saya bertanya-tanya bagaimana IDE terintegrasi dengan kerangka kerja JUnit. Jika saya memiliki test case yang sudah berjalan lama seperti

<strong i="8">@Test</strong>
  public void test1() throws InterruptedException {
    Thread.sleep(100000);
  }

<strong i="9">@Test</strong>
  public void test2() throws InterruptedException {
    Thread.sleep(100000);
  }

dan saya menghentikan test case dengan paksa menggunakan IDE. Akankah IDE mengganggu Thread yang menjalankan tes JUnit atau yang lainnya?
Saya memeriksa perilaku di IntelliJ, tampaknya mereka menjalankan proses yang berbeda dan mengganggu proses ketika kasus uji dihentikan secara paksa dari IDE. Saya melihat Process finished with exit code 130 (interrupted by signal 2: SIGINT) di konsol.
Saya pergi melalui sumber Eclipse JDT dan menemukan bahwa mereka menggunakan semacam koneksi jarak jauh untuk eksekusi kasus uji.

Keraguan saya adalah dengan cara kita melanggar konvensi Thread.interrupted() dengan tidak menghormati interupsi dan menelannya. Jadi saya pikir jika integrasi IDE benar-benar menggunakan junitThread.interrupt() untuk menghentikan eksekusi lebih lanjut dari tes JUnit maka itu tidak akan memenuhi permintaan itu. Jadi dalam hal ini ketika test1 dijalankan dan saya mengklik tombol stop dari IDE, itu akan memungkinkan metode saat ini untuk dieksekusi dan tidak menjalankan kasus uji lebih lanjut. Apakah perilaku ini akan terpengaruh dengan menyetel ulang tanda status interupsi.

Saya minta maaf jika pertanyaannya bodoh, saya tidak punya pengalaman dengan bagaimana IDE terintegrasi. Akan sangat bagus jika Anda bisa memberi saya pencerahan.

@ npathai Saya pikir IDE memanggil RunNotifier.pleaseStop()

Jadi sepertinya kekhawatirannya adalah ini: apa yang terjadi jika IDE memanggil pleaseStop() lalu Thread.interrupt() pada utas yang menjalankan tes?

Jika utas tersebut tidak dalam metode pemblokiran dan tidak memanggil metode pemblokiran, pengujian akan dibatalkan setelah pengujian saat ini selesai (karena pleaseStop() ).

Jika utas itu dalam metode pemblokiran atau memanggil metode pemblokiran, itu akan membuang InterruptedException . Jika tes tidak menangkap pengecualian itu akan gagal, maka uji coba akan dibatalkan.

Jika tes menelan pengecualian, semuanya menjadi rumit.

Kami menggunakan pleaseStop() di Surefire. Kami mengandalkan perilaku saat ini bahwa
Penjadwal JUnit berhenti menjadwalkan Runnable baru (metode pengujian) tetapi
metode tertunda berlangsung.

Pada Jumat, 9 November 2018 pukul 17:48 Kevin Cooney [email protected]
menulis:

Jadi sepertinya kekhawatirannya adalah ini: apa yang terjadi jika IDE memanggil
pleaseStop() lalu Thread.interrupt() pada utas yang menjalankan tes?

Jika utas itu tidak dalam metode pemblokiran dan tidak memanggil pemblokiran
metode, uji coba akan dibatalkan setelah pengujian saat ini selesai (karena
tolong hentikan()

Jika utas itu dalam metode pemblokiran atau memanggil metode pemblokiran, itu akan
membuang InterruptedException. Jika tes tidak menangkap pengecualian itu, itu
akan gagal, maka uji coba akan dibatalkan.

Jika tes menelan pengecualian, semuanya menjadi rumit.


Anda menerima ini karena Anda berlangganan utas ini.
Balas email ini secara langsung, lihat di GitHub
https://github.com/junit-team/junit4/issues/1365#issuecomment-437420750 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AA_yR9IgJF3rTXtFz9y9EIBig914twYYks5utbHrgaJpZM4KIg2k
.

--
Bersulang
Tibor

Bukankah ini harus dipilih untuk JUnit 5? Saya mengalami masalah yang sama dengan 5.3.2.

@joaodias14 Harap tingkatkan ke versi terbaru, sudah diperbaiki di 5.4.0 (lihat https://github.com/junit-team/junit5/issues/1688).

Terima kasih banyak @marcphilipp!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

gitIvanB picture gitIvanB  ·  9Komentar

kcooney picture kcooney  ·  108Komentar

kluever picture kluever  ·  16Komentar

pbenedict picture pbenedict  ·  27Komentar

diogoeag picture diogoeag  ·  35Komentar