Menjalankan Ujian JUnit Selari dengan Maven

1. Pengenalan

Walaupun menjalankan ujian secara bersiri berfungsi dengan baik pada kebanyakan masa, kami mungkin ingin memaralelkannya untuk mempercepat.

Dalam tutorial ini, kita akan membahas bagaimana untuk menyelaraskan ujian menggunakan JUnit dan Maven's Surefire Plugin. Pertama, kami akan menjalankan semua ujian dalam satu proses JVM, kemudian kami akan mencubanya dengan projek multi-modul.

2. Pergantungan Maven

Mari mulakan dengan mengimport kebergantungan yang diperlukan. Kita perlu menggunakan JUnit 4.7 atau lebih baru bersama dengan Surefire 2.16 atau lebih baru:

 junit junit 4.12 test 
 org.apache.maven.plugins maven-surefire-plugin 2.22.0 

Ringkasnya, Surefire menyediakan dua cara untuk melaksanakan ujian secara selari:

  • Multithreading dalam satu proses JVM
  • Memaksakan pelbagai proses JVM

3. Menjalankan Ujian Selari

Untuk menjalankan ujian secara selari kita harus menggunakan test runner yang memanjangkan org.junit.runners.ParentRunner .

Walau bagaimanapun, walaupun ujian yang tidak menyatakan pelari ujian eksplisit berfungsi, kerana pelari lalai melanjutkan kelas ini.

Seterusnya, untuk menunjukkan pelaksanaan ujian selari, kami akan menggunakan suite ujian dengan dua kelas ujian masing-masing mempunyai beberapa kaedah. Sebenarnya, sebarang pelaksanaan standard dari rangkaian ujian JUnit akan berlaku.

3.1. Menggunakan Parameter Selari

Pertama, mari aktifkan tingkah laku selari di Surefire menggunakan parameter selari . Ia menyatakan tahap butiran di mana kita ingin menerapkan paralelisme.

Nilai yang mungkin adalah:

  • kaedah - menjalankan kaedah ujian dalam utas yang berasingan
  • kelas - menjalankan kelas ujian dalam utas yang berasingan
  • classAndMethods - menjalankan kelas dan kaedah dalam utas yang berasingan
  • suite - menjalankan suite secara selari
  • suitesAndClasses - menjalankan suite dan kelas dalam utas yang berasingan
  • suitesAndMethods - membuat utas berasingan untuk kelas dan kaedah
  • semua - menjalankan suite, kelas dan juga kaedah dalam utas yang berasingan

Dalam contoh kami, kami menggunakan semua :

 all 

Kedua, mari kita tentukan jumlah utas yang kita mahu Surefire buat. Kita boleh melakukannya dengan dua cara:

Menggunakan threadCount yang menentukan bilangan maksimum utas yang akan dibuat oleh Surefire:

10

Atau menggunakan parameter useUnlimitedThreads di mana satu utas dibuat setiap teras CPU:

true

Secara lalai, threadCount adalah setiap teras CPU. Kita boleh menggunakan parameter perCoreThreadCount untuk mengaktifkan atau mematikan tingkah laku ini:

true

3.2. Menggunakan Had Thread-Count

Sekarang, katakan kita mahu menentukan bilangan utas yang akan dibuat pada tahap kaedah, kelas, dan suite. Kita boleh melakukannya dengan parameter threadCountMethods , threadCountClasses dan threadCountSuites .

Mari gabungkan parameter ini dengan threadCount dari konfigurasi sebelumnya:

2 2 6

Oleh kerana kami menggunakan semua secara selari, kami telah menentukan bilangan utas untuk kaedah, suite dan kelas. Walau bagaimanapun, tidak wajib menentukan parameter daun. Surefire menyimpulkan bilangan utas yang akan digunakan sekiranya parameter daun dihilangkan.

Sebagai contoh, jika threadCountMethods dihilangkan, maka kita hanya perlu memastikan threadCount > threadCountClasses + threadCountSuites.

Kadang-kadang kita mungkin mahu mengehadkan bilangan utas yang dibuat untuk kelas atau suite atau kaedah walaupun kita menggunakan bilangan utas yang tidak terhad.

Kami juga boleh menggunakan had jumlah benang dalam kes seperti itu:

true 2

3.3. Menetapkan Waktu Tamat

Kadang-kadang kita mungkin perlu memastikan bahawa pelaksanaan ujian adalah mengikut masa.

Untuk melakukan itu kita boleh menggunakan parameter parallelTestTimeoutForcedInSeconds . Ini akan mengganggu urutan yang sedang berjalan dan tidak akan menjalankan sebarang urutan yang beratur setelah tamat masa:

5

Pilihan lain adalah menggunakan parallelTestTimeoutInSeconds .

Dalam kes ini, hanya urutan yang beratur yang akan berhenti menjalankan:

3.5

Walaupun begitu, dengan kedua-dua pilihan tersebut, ujian akan berakhir dengan mesej ralat apabila waktu tamat telah berlalu.

3.4. Kaveat

Surefire memanggil kaedah statik yang dianotasi dengan @Parameters , @BeforeClass , dan @AfterClass dalam utas induk. Oleh itu, pastikan untuk memeriksa kemungkinan percanggahan ingatan atau keadaan perlumbaan sebelum menjalankan ujian secara selari.

Juga, ujian yang mengubah keadaan bersama pasti bukan calon yang baik untuk berjalan selari.

4. Uji Pelaksanaan dalam Projek Maven Multi-Modul

Hingga kini, kami telah menumpukan pada menjalankan ujian secara selari dalam modul Maven.

Tetapi katakan kita mempunyai banyak modul dalam projek Maven. Oleh kerana modul ini dibina secara berurutan, ujian untuk setiap modul juga dijalankan secara berurutan.

Kita boleh mengubah tingkah laku lalai ini dengan menggunakan parameter -T Maven yang membina modul secara selari . Ini boleh dilakukan dengan dua cara.

Kita boleh menentukan bilangan utas yang tepat untuk digunakan semasa membina projek:

mvn -T 4 surefire:test

Atau gunakan versi mudah alih dan tentukan bilangan utas untuk dibuat setiap teras CPU:

mvn -T 1C surefire:test

Walau bagaimana pun, kita dapat mempercepat ujian serta membina masa pelaksanaan.

5. JVM forking

Dengan pelaksanaan ujian selari melalui pilihan selari , serentak berlaku di dalam proses JVM menggunakan utas .

Oleh kerana benang berkongsi ruang memori yang sama, ini dapat menjadi efisien dari segi memori dan kelajuan. Walau bagaimanapun, kami mungkin menghadapi keadaan perlumbaan yang tidak dijangka atau kegagalan ujian lain yang berkaitan secara bersamaan. Ternyata, berkongsi ruang memori yang sama boleh menjadi berkat dan kutukan.

Untuk mengelakkan masalah serentak peringkat utas, Surefire menyediakan satu lagi mod pelaksanaan ujian selari: persempadanan dan peringkat proses . Idea proses bercabang sebenarnya agak mudah. Daripada melahirkan beberapa benang dan menyebarkan kaedah ujian di antara mereka, surefire membuat proses baru dan melakukan pengedaran yang sama.

Oleh kerana tidak ada memori bersama antara proses yang berbeza, kami tidak akan mengalami bug bersamaan yang halus. Sudah tentu, ini mengorbankan penggunaan memori yang lebih banyak dan sedikit kelajuan.

Bagaimanapun, untuk mengaktifkan forking, kita hanya perlu menggunakan harta forkCount dan menetapkannya kepada nilai positif:

3

Di sini, surefire akan membuat paling banyak tiga garpu dari JVM dan menjalankan ujian di dalamnya. Nilai lalai untuk forkCount adalah satu, yang bermaksud bahawa maven-surefire-plugin membuat satu proses JVM baru untuk melaksanakan semua ujian dalam satu modul Maven.

The forkCount harta menyokong sintaks yang sama seperti -T . Artinya, jika kita menambahkan C ke nilai, nilai itu akan dikalikan dengan jumlah inti CPU yang tersedia di sistem kita. Contohnya:

2.5C

Kemudian dalam mesin dua teras, Surefire dapat membuat paling banyak lima garpu untuk pelaksanaan ujian selari.

Secara lalai, Surefire akan menggunakan semula garpu yang dibuat untuk ujian lain . Walau bagaimanapun, jika kita menetapkan properti reuseForks menjadi palsu , ia akan menghancurkan setiap garpu setelah menjalankan satu kelas ujian.

Juga, untuk mematikan forking, kita dapat menetapkan forkCount ke sifar.

6. Kesimpulannya

Kesimpulannya, kami memulakan dengan mengaktifkan tingkah laku berbilang utas dan menentukan tahap paralelisme menggunakan parameter selari . Selepas itu, kami menerapkan batasan pada bilangan utas yang mesti dibuat oleh Surefire. Kemudian, kami menetapkan parameter timeout untuk mengawal masa pelaksanaan ujian.

Akhirnya, kami melihat bagaimana kami dapat mengurangkan masa pelaksanaan binaan dan oleh itu menguji masa pelaksanaan dalam projek Maven pelbagai modul.

Seperti biasa, kod yang disajikan di sini boleh didapati di GitHub.