Pengantar HtmlUnit

1. Perkenalan

Pada artikel ini, kami akan memperkenalkan HtmlUnit, alat yang memungkinkan kami untuk, secara sederhana, berinteraksi dengan dan menguji situs HTML secara terprogram, menggunakan JAVA API .

2. Tentang HtmlUnit

HtmlUnit adalah peramban tanpa GUI - peramban yang dimaksudkan untuk digunakan secara terprogram dan tidak secara langsung oleh pengguna.

Browser mendukung JavaScript (melalui mesin Mozilla Rhino) dan dapat digunakan bahkan untuk situs web dengan fungsi AJAX yang kompleks. Semua ini dapat dilakukan dengan mensimulasikan browser berbasis GUI seperti Chrome atau Firefox.

Nama HtmlUnit dapat membuat Anda berpikir bahwa ini adalah kerangka pengujian, tetapi meskipun pasti dapat digunakan untuk pengujian, ia dapat melakukan lebih dari itu.

Ini juga telah diintegrasikan ke dalam Spring 4 dan dapat digunakan dengan mulus bersama dengan kerangka kerja Spring MVC Test.

3. Unduh dan Ketergantungan Maven

HtmlUnit dapat diunduh dari SourceForge atau dari situs resminya. Selain itu, Anda dapat memasukkannya ke dalam alat bangunan Anda (seperti Maven atau Gradle, antara lain) seperti yang Anda lihat di sini. Misalnya, ini adalah ketergantungan Maven yang saat ini dapat Anda sertakan dalam proyek Anda:

 net.sourceforge.htmlunit htmlunit 2.23  

Versi terbaru dapat ditemukan di sini.

4. Pengujian Web

Ada banyak cara untuk menguji aplikasi web - sebagian besar telah kami bahas di sini pada satu titik atau lainnya.

Dengan HtmlUnit Anda dapat langsung mengurai HTML situs, berinteraksi dengannya seperti yang dilakukan pengguna biasa dari browser, memeriksa sintaks JavaScript dan CSS, mengirimkan formulir, dan mengurai tanggapan untuk melihat konten elemen HTML-nya. Semua itu, menggunakan kode Java murni.

Mari kita mulai dengan tes sederhana: buat Klien Web dan dapatkan halaman pertama navigasi www.baeldung.com :

private WebClient webClient; @Before public void init() throws Exception { webClient = new WebClient(); } @After public void close() throws Exception { webClient.close(); } @Test public void givenAClient_whenEnteringBaeldung_thenPageTitleIsOk() throws Exception  HtmlPage page = webClient.getPage("/"); Assert.assertEquals( "Baeldung  

Anda dapat melihat beberapa peringatan atau kesalahan saat menjalankan tes tersebut jika situs web kami memiliki masalah JavaScript atau CSS. Anda harus memperbaikinya.

Terkadang, jika Anda tahu apa yang Anda lakukan (misalnya, jika Anda melihat bahwa satu-satunya kesalahan yang Anda miliki adalah dari pustaka JavaScript pihak ketiga yang tidak boleh Anda ubah) Anda dapat mencegah kesalahan ini membuat pengujian Anda gagal, memanggil setThrowExceptionOnScriptError dengan salah :

@Test public void givenAClient_whenEnteringBaeldung_thenPageTitleIsCorrect() throws Exception  Java, Spring and Web Development tutorials", page.getTitleText()); 

5. Scraping Web

Anda tidak perlu menggunakan HtmlUnit hanya untuk situs web Anda sendiri. Bagaimanapun, ini adalah browser: Anda dapat menggunakannya untuk menavigasi web apa pun yang Anda suka, mengirim dan mengambil data sesuai kebutuhan.

Mengambil, mengurai, menyimpan, dan menganalisis data dari situs web adalah proses yang dikenal sebagai web scraping dan HtmlUnit dapat membantu Anda dengan bagian pengambilan dan penguraian.

Contoh sebelumnya menunjukkan bagaimana kita dapat memasuki situs web apa pun dan menavigasi melaluinya, mengambil semua info yang kita inginkan.

Sebagai contoh, mari kita pergi ke arsip lengkap artikel Baeldung, menavigasi ke artikel terbaru dan mengambil judulnya (pertama

menandai). Untuk pengujian kami, itu sudah cukup; tetapi, jika kita ingin menyimpan lebih banyak info, kita bisa, misalnya, mengambil heading (all

tag) juga, sehingga memiliki gagasan dasar tentang artikel tersebut.

Sangat mudah untuk mendapatkan elemen berdasarkan ID mereka, tetapi secara umum, jika Anda perlu menemukan elemen, lebih mudah menggunakan sintaks XPath . HtmlUnit memungkinkan kita untuk menggunakannya, jadi kita akan menggunakannya.

@Test public void givenBaeldungArchive_whenRetrievingArticle_thenHasH1() throws Exception { webClient.getOptions().setCssEnabled(false); webClient.getOptions().setJavaScriptEnabled(false); String url = "/full_archive"; HtmlPage page = webClient.getPage(url); String xpath = "(//ul[@class='car-monthlisting']/li)[1]/a"; HtmlAnchor latestPostLink = (HtmlAnchor) page.getByXPath(xpath).get(0); HtmlPage postPage = latestPostLink.click(); List h1 = (List) postPage.getByXPath("//h1"); Assert.assertTrue(h1.size() > 0); } 

Pertama perhatikan bagaimana - dalam hal ini, kami tidak tertarik dengan CSS atau JavaScript dan hanya ingin mengurai tata letak HTML, jadi kami menonaktifkan CSS dan JavaScript.

Dalam web scraping yang sebenarnya, Anda dapat mengambil contoh judul h1 dan h2 , dan hasilnya akan seperti ini:

Java Web Weekly, Issue 135 1. Spring and Java 2. Technical and Musings 3. Comics 4. Pick of the Week

Anda dapat memeriksa bahwa info yang diambil sesuai dengan artikel terbaru di Baeldung memang:

6. Bagaimana dengan AJAX?

Fungsionalitas AJAX bisa menjadi masalah karena HtmlUnit biasanya akan mengambil halaman sebelum panggilan AJAX selesai. Sering kali Anda membutuhkan mereka untuk menyelesaikan pengujian situs web Anda dengan benar atau untuk mengambil data yang Anda inginkan. Ada beberapa cara untuk mengatasinya:

  • You can use webClient.setAjaxController(new NicelyResynchronizingAjaxController()). This resynchronizes calls performed from the main thread and these calls are performed synchronously to ensure that there is a stable state to test.
  • When entering a page of a web application, you can wait for some seconds so there is enough time to let AJAX calls finish. To achieve this, you can use webClient.waitForBackgroundJavaScript(MILLIS) or webClient.waitForBackgroundJavaScriptStartingBefore(MILLIS). You should call them after retrieving the page, but before working with it.
  • You can wait until some expected condition related to the execution of the AJAX call is met. For instance:
for (int i = 0; i < 20; i++) { if (condition_to_happen_after_js_execution) { break; } synchronized (page) { page.wait(500); } }
  • Instead of creating a new WebClient(), that defaults to the best-supported web browser, try other browsers since they might work better with your JavaScript or AJAX calls. For instance, this will create a webClient that uses a Chrome browser:
WebClient webClient = new WebClient(BrowserVersion.CHROME);

7. An Example With Spring

If we're testing our own Spring application, then things get a little bit easier – we no longer need a running server.

Let's implement a very simple example app: just a controller with a method that receives a text, and a single HTML page with a form. The user can input a text into the form, submit the form, and the text will be shown below that form.

In this case, we'll use a Thymeleaf template for that HTML page (you can see a complete Thymeleaf example here):

@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = { TestConfig.class }) public class HtmlUnitAndSpringTest { @Autowired private WebApplicationContext wac; private WebClient webClient; @Before public void setup() { webClient = MockMvcWebClientBuilder .webAppContextSetup(wac).build(); } @Test public void givenAMessage_whenSent_thenItShows() throws Exception { String text = "Hello world!"; HtmlPage page; String url = "//localhost/message/showForm"; page = webClient.getPage(url); HtmlTextInput messageText = page.getHtmlElementById("message"); messageText.setValueAttribute(text); HtmlForm form = page.getForms().get(0); HtmlSubmitInput submit = form.getOneHtmlElementByAttribute( "input", "type", "submit"); HtmlPage newPage = submit.click(); String receivedText = newPage.getHtmlElementById("received") .getTextContent(); Assert.assertEquals(receivedText, text); } }

The key here is building the WebClient object using MockMvcWebClientBuilder from the WebApplicationContext. With the WebClient, we can get the first page of the navigation (notice how it's served by localhost), and start browsing from there.

As you can see, the test parses the form enters a message (in a field with ID “message”), submits the form and, on the new page, it asserts that the received text (field with ID “received”) is the same as the text we submitted.

8. Conclusion

HtmlUnit is a great tool that allows you to test your web applications easily, filling forms fields and submitting them just as if you were using the web on a browser.

Ini terintegrasi secara mulus dengan Spring 4, dan bersama dengan kerangka kerja Spring MVC Test mereka memberi Anda lingkungan yang sangat kuat untuk membuat tes integrasi semua halaman Anda bahkan tanpa server web.

Selain itu, menggunakan HtmlUnit Anda dapat mengotomatiskan tugas apa pun yang terkait dengan penjelajahan web, seperti mengambil, mengurai, menyimpan, dan menganalisis data (scraping web).

Anda bisa mendapatkan kodenya di Github.