Uji aplikasi Web dengan HttpUnit

Dalam aplikasi perusahaan pada umumnya, banyak area memerlukan pengujian. Mulai dari komponen yang paling sederhana, class, developer atau developer pengujian khusus perlu memprogram pengujian unit untuk memastikan bahwa unit terkecil aplikasi berperilaku dengan benar. Setiap komponen berpotensi lulus tes unit sendiri; namun pengembang perlu memastikan mereka bekerja sama seperti yang diharapkan — sebagai bagian dari subsistem, dan sebagai bagian dari keseluruhan aplikasi — karenanya, pengujian integrasi harus dilakukan. Dalam beberapa proyek, persyaratan kinerja harus dipenuhi, sehingga teknisi jaminan kualitas melakukan uji beban untuk memverifikasi dan mendokumentasikan bagaimana kinerja aplikasi dalam berbagai kondisi. Selama pengembangan aplikasi, teknisi jaminan kualitas melakukan uji fungsional otomatis dan manualuntuk menguji perilaku aplikasi dari sudut pandang pengguna. Ketika proyek pengembangan hampir menyelesaikan tonggak tertentu, tes penerimaan dapat dilakukan untuk memverifikasi bahwa aplikasi memenuhi persyaratan.

HttpUnit adalah kerangka kerja berdasarkan JUnit, yang memungkinkan implementasi skrip pengujian otomatis untuk aplikasi Web. Ini paling cocok untuk implementasi tes fungsional otomatis, atau tes penerimaan. Seperti namanya, ini dapat digunakan untuk pengujian unit; namun, komponen lapisan Web biasa seperti halaman JSP (JavaServer Pages), servlet, dan komponen template lainnya tidak cocok untuk pengujian unit. Adapun berbagai komponen berbasis kerangka kerja MVC (Model-View Controller), ini lebih cocok untuk pengujian dengan kerangka kerja pengujian lainnya. Tindakan struts dapat diuji unitnya dengan StrutsUnit, dan tindakan WebWork 2 dapat diuji unitnya tanpa wadah Web, misalnya.

Uji target

Sebelum kita beralih ke detail arsitektur dan implementasi, penting untuk mengklarifikasi dengan tepat apa yang perlu dibuktikan oleh skrip pengujian tentang aplikasi Web. Dimungkinkan untuk hanya mensimulasikan perilaku pengunjung situs web biasa dengan hanya mengklik tautan yang menarik dan membaca halaman dalam urutan acak, tetapi hasil dari skrip acak ini tidak akan menggambarkan kelengkapan dan kualitas aplikasi.

Aplikasi Web perusahaan yang khas (atau Situs web yang kompleks) memiliki beberapa dokumen yang menjelaskan persyaratan berbagai pengguna atau pengelola aplikasi. Ini dapat mencakup spesifikasi kasus penggunaan, spesifikasi persyaratan nonfungsional, spesifikasi kasus uji yang berasal dari artefak lain, dokumen desain antarmuka pengguna, maket, profil aktor, dan berbagai artefak tambahan. Untuk aplikasi sederhana, seluruh spesifikasi mungkin terdiri dari file teks sederhana dengan daftar persyaratan.

Dari dokumen-dokumen ini, kita harus membuat daftar kasus uji yang terorganisir. Setiap kasus uji menggambarkan skenario yang dapat diselesaikan oleh pengunjung Web melalui browser Web. Praktik yang baik adalah membidik skenario berukuran serupa — skenario yang lebih besar dapat dipecah menjadi bagian yang lebih kecil. Banyak buku dan artikel yang bagus membahas pembuatan spesifikasi kasus uji. Untuk artikel ini, anggaplah Anda memiliki sekumpulan item yang ingin Anda uji untuk aplikasi Web Anda, diatur ke dalam sekumpulan skenario kasus uji.

Waktunya mengunduh barang!

Oke, sekarang kita tahu hal-hal yang membosankan, yuk download beberapa mainan keren! Pertama-tama, kita membutuhkan Java 2 SDK yang diinstal untuk mengkompilasi dan menjalankan pengujian kita. Kemudian kita perlu mendownload framework HttpUnit — saat ini di versi 1.5.5. Paket biner berisi semua pustaka pihak ketiga yang diperlukan. Kami juga memerlukan alat build Ant untuk menjalankan pengujian dan menghasilkan laporan secara otomatis. Versi yang cukup baru dari alat ini mungkin akan bekerja; Saya lebih suka menggunakan versi terbaru dan terbaik dari semuanya.

Untuk menulis dan menjalankan pengujian, saya merekomendasikan menggunakan IDE yang memiliki runner pengujian JUnit tertanam. Saya menggunakan Eclipse 3.0M7 untuk mengembangkan skrip pengujian saya, tetapi IntelliJ juga memiliki dukungan JUnit, seperti halnya IDE yang dirilis baru-baru ini.

HttpUnit: Simulator klien HTTP

Karena kami ingin menguji aplikasi Web, idealnya, alat pengujian harus berperilaku persis seperti browser Web pengguna. Aplikasi kita (target pengujian) seharusnya tidak mengetahui perbedaan apa pun saat menyajikan halaman ke browser Web atau alat pengujian. Itulah tepatnya yang disediakan HttpUnit: ia mensimulasikan permintaan GET dan POST browser normal, dan menyediakan model objek yang bagus untuk mengkodekan pengujian kami.

Lihat panduan API terperinci untuk kelas dan metode lainnya; Gambar 1 hanya memberikan gambaran singkat tentang kelas yang paling sering saya gunakan. Sesi pengguna (urutan interaksi dengan aplikasi Web) dienkapsulasi dengan a WebConversation. Kami membuat WebRequests, biasanya mengkonfigurasi URL dan parameternya, dan kemudian kami mengirimkannya melalui WebConversation. Framework kemudian mengembalikan a WebResponse, yang berisi halaman yang dikembalikan dan atribut dari server.

Berikut adalah contoh kasus uji HttpUnit dari dokumen HttpUnit:

/ ** * Memverifikasi bahwa mengirimkan formulir login dengan nama "master" menghasilkan * di halaman yang berisi teks "Top Secret" ** / public void testGoodLogin () akan melempar Exception {WebConversation Conversation = new WebConversation (); WebRequest request = new GetMethodWebRequest ("//www.meterware.com/servlet/TopSecret"); WebResponse response = percakapan.getResponse (permintaan); WebForm loginForm = response.getForms () [0]; request = loginForm.getRequest (); request.setParameter ("name", "master"); response = percakapan.getResponse (permintaan); assertTrue ("Login tidak diterima", response.getText (). indexOf ("Anda berhasil!")! = -1); assertEquals ("Judul halaman", "Sangat Rahasia", response.getTitle ()); }

Pertimbangan arsitektur

Perhatikan bagaimana contoh Java di atas berisi nama domain server yang menjalankan aplikasi. Selama pengembangan sistem baru, aplikasi berada di beberapa server, dan server dapat menjalankan beberapa versi. Jelas merupakan ide yang buruk untuk mempertahankan nama server dalam implementasi Java — untuk setiap server baru, kita perlu mengkompilasi ulang sumber kita. Item lain tidak boleh berada di file sumber, seperti nama pengguna dan sandi, yang harus dapat dikonfigurasi untuk penerapan tertentu. Di sisi lain, kita tidak boleh merancang implementasi kasus uji yang sederhana secara berlebihan. Biasanya spesifikasi kasus uji sudah berisi sebagian besar status sistem dan deskripsi parameter spesifik untuk skenario kita, jadi tidak ada gunanya membuat semuanya dapat dijadikan parameter dalam implementasi.

Selama pengkodean, Anda akan menyadari bahwa banyak bagian kode muncul di lebih dari satu implementasi kasus uji (berpotensi di semua kasus uji). Jika Anda adalah pengembang berorientasi objek yang berpengalaman, Anda akan tergoda untuk membuat hierarki kelas dan kelas umum. Dalam beberapa kasus, itu sangat masuk akal — misalnya, prosedur login harus menjadi metode umum yang tersedia untuk semua kasus pengujian. Namun, Anda perlu mundur sedikit dan menyadari bahwa Anda tidak membangun sistem produksi baru di atas aplikasi target-of-test — kelas Java ini tidak lebih dari skrip pengujian untuk memvalidasi keluaran Situs Web. Gunakan akal sehat dan bidik skrip pengujian yang sederhana, berurutan, dan mandiri.

Kasus uji biasanya rapuh. Jika pengembang mengubah URL, mengatur ulang tata letaknya

akan sederhana, skrip berurutan

Ketertelusuran sangat penting untuk kasus pengujian kami. Jika terjadi KA-BOOM, atau, misalnya, hasil kalkulasi salah, penting untuk mengarahkan pengembang ke spesifikasi kasus uji yang sesuai dan spesifikasi kasus penggunaan untuk resolusi bug cepat. Oleh karena itu, beri anotasi penerapan Anda dengan referensi ke dokumen spesifikasi asli. Menyertakan nomor versi dari dokumen tersebut juga berguna. Itu bisa berupa komentar kode sederhana atau mekanisme kompleks di mana laporan pengujian itu sendiri tertaut ke dokumen; yang penting adalah memiliki referensi dalam kode dan menjaga ketertelusuran.

Kapan saya bisa menulis kode?

Sekarang setelah Anda mengetahui persyaratannya (dokumen kasus penggunaan dan spesifikasi kasus uji yang sesuai), memahami dasar-dasar kerangka kerja, dan memiliki seperangkat pedoman arsitektur, mari mulai bekerja.

Untuk pengembangan implementasi kasus uji, saya lebih suka bekerja di Eclipse. Pertama-tama, ia memiliki runner pengujian JUnit yang bagus. Anda dapat memilih kelas Java, dan dari menu Run, Anda dapat menjalankannya sebagai pengujian unit JUnit. Runner menampilkan daftar metode pengujian yang dikenali dan hasil eksekusi. Ketika semuanya berjalan baik-baik saja selama uji coba, itu memberikan garis hijau yang bagus. Jika pengecualian atau kegagalan pernyataan terjadi, ini akan menampilkan garis merah yang mengganggu. Saya pikir umpan balik visual sangat penting — ini menawarkan rasa pencapaian, terutama saat menulis pengujian unit untuk kode Anda sendiri. Saya juga suka menggunakan Eclipse untuk kemampuan refactoring-nya. Jika saya menyadari bahwa dalam kelas kasus uji saya perlu menyalin dan menempel bagian kode, saya dapat menggunakan menu Refactoring untuk membuat metode dari bagian kode sebagai gantinya.Jika saya menyadari bahwa banyak kasus pengujian akan menggunakan metode yang sama, saya dapat menggunakan menu untuk menarik metode saya ke kelas dasar saya.

Based on the architectural requirements above, for each project, I typically create a base test-case class, which extends the JUnit TestCase class. I call it ConfigurableTestCase. Each test-case implementation extends this class, see Figure 2.

ConfigurableTestCase typically contains the common methods and initialization code for the test case. I use a property file to store the server name, the application context, various login names for each role, and some additional settings.

The specific test-case implementations contain one test method per test-case scenario (from the test-case specification document). Each method typically logs in with a specific role and then executes the interaction with the Web application. Most test cases do not need a specific user to accomplish the activities; they typically require a user in a specific role, like Administrator, or Visitor, or Registered User. I always create a LoginMode enum, which contains the available roles. I use the Jakarta Commons ValuedEnum package to create enums for the roles. When a specific test method in a test-case implementation logs in, it must specify which login role is required for that particular test scenario. Of course, the ability to log in with a specific user should also be possible, for example, to verify the Registered User use case.

After each request and response cycle, we typically need to verify if the returned page contains an error, and we need to verify our assertions about what content the response should contain. We must be careful here as well; we should only verify items that are not variable and not too fragile in the application. For example, if we assert specific page titles, our tests will probably not run if the language is selectable in the application and we want to verify a different language deployment. Similarly, there's little point in checking an item on the page based on its position within a table layout; table-based designs change frequently, so we should strive to identify elements based on their IDs. In case some important elements on the page don't have IDs or names, we should just ask the developers to add them, rather than trying to work around them.

JUnit assertions offer a poor approach for checking if the look and feel, layout, and page design comply with the requirements. It is possible, given an infinite amount of time for the test development, but a good human tester can assess these things more efficiently. So concentrate on verifying the Web application's functionality, rather than checking everything possible on the page.

Here's an updated test scenario based on our test-case architecture. The class extends ConfigurableTestCase, and the login details are handled in the base class:

 /** * Verifies that submitting the login form with the name "master" results * in a page containing the text "Top Secret" **/ public void testGoodLogin() throws Exception { WebConversation conversation = new WebConversation(); WebResponse response = login(conversation, LoginMode.ADMIN_MODE); assertTrue( "Login not accepted", response.getText().indexOf( "You made it!" ) != -1 ); assertEquals( "Page title", "Top Secret", response.getTitle() ); } 

Tips and tricks

Most scenarios can be handled quite easily by setting WebForm parameters and then looking for specific elements with results in the WebResponse pages, but there are always some challenging test cases.





struktur, atau mengubah ID elemen formulir, pengunjung mungkin tidak akan melihat perbedaan apa pun, tetapi skrip pengujian Anda rusak. Harapkan banyak pengerjaan ulang dan perubahan untuk setiap implementasi kasus uji. Desain berorientasi objek dapat mengurangi upaya pengerjaan ulang bagian umum dalam kasus pengujian, tetapi dari perspektif insinyur atau penguji jaminan kualitas, saya yakin bahwa yang berinteraksi dengan Situs Web lebih mudah untuk dipelihara dan diperbaiki. #####