Introduktion till HtmlUnit

1. Introduktion

I den här artikeln kommer vi att presentera HtmlUnit, ett verktyg som låter oss, enkelt uttrycka, interagera med och testa en HTML-webbplats programmatiskt, med hjälp av JAVA API: er .

2. Om HtmlUnit

HtmlUnit är en webbläsare utan GUI - en webbläsare avsedd att användas programmatiskt och inte direkt av en användare.

Webbläsaren stöder JavaScript (via Mozilla Rhino-motorn) och kan användas även för webbplatser med komplexa AJAX-funktioner. Allt detta kan göras för att simulera en typisk GUI-baserad webbläsare som Chrome eller Firefox.

Namnet HtmlUnit kan få dig att tro att det är ett testramverk, men även om det definitivt kan användas för testning kan det göra så mycket mer än så.

Den har också integrerats i vår 4 och kan användas sömlöst tillsammans med Spring MVC Test-ramverk.

3. Ladda ner och Maven-beroende

HtmlUnit kan laddas ner från SourceForge eller från den officiella webbplatsen. Du kan också inkludera det i ditt byggverktyg (som Maven eller Gradle, bland andra) som du kan se här. Till exempel är detta det Maven-beroende du för närvarande kan inkludera i ditt projekt:

 net.sourceforge.htmlunit htmlunit 2.23  

Den senaste versionen finns här.

4. Webbtestning

Det finns många sätt på vilket du kan testa en webbapplikation - de flesta av dessa behandlade vi här på webbplatsen vid ett eller annat tillfälle.

Med HtmlUnit kan du analysera HTML på en webbplats direkt, interagera med den precis som en vanlig användare skulle göra från webbläsaren, kontrollera JavaScript och CSS-syntax, skicka formulär och analysera svaren för att se innehållet i dess HTML-element. Allt med ren Java-kod.

Låt oss börja med ett enkelt test: skapa en WebClient och få den första sidan i navigeringen på 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  

Du kan se några varningar eller fel när du kör det testet om vår webbplats har JavaScript- eller CSS-problem. Du borde rätta till dem.

Ibland, om du vet vad du gör (till exempel om du ser att de enda felen du har är från JavaScript-bibliotek från tredje part som du inte ska ändra) kan du förhindra att dessa fel gör att ditt test misslyckas, ringer setThrowExceptionOnScriptError med falsk :

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

5. Webbskrapning

Du behöver inte använda HtmlUnit bara för dina egna webbplatser. Det är trots allt en webbläsare: du kan använda den för att navigera genom vilken web som helst, skicka och hämta data efter behov.

Att hämta, analysera, lagra och analysera data från webbplatser är den process som kallas webbskrapning och HtmlUnit kan hjälpa dig med att hämta och analysera delar.

Det föregående exemplet visar hur vi kan komma in på vilken webbplats som helst och navigera genom den och hämta all information vi vill ha.

Låt oss till exempel gå till Baeldungs ​​fullständiga arkiv med artiklar, navigera till den senaste artikeln och hämta titeln (först

märka). För vårt test kommer det att räcka; men om vi ville lagra mer info kan vi till exempel hämta rubrikerna (alla

taggar), och har därmed en grundläggande uppfattning om vad artikeln handlar om.

Det är lätt att få element efter deras ID, men i allmänhet, om du behöver hitta ett element är det bekvämare att använda XPath-syntax . HtmlUnit tillåter oss att använda det, så kommer vi att göra det.

@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); } 

Först notera hur - i det här fallet är vi inte intresserade av CSS eller JavaScript och vill bara analysera HTML-layouten, så vi stängde av CSS och JavaScript.

I en riktig webbskrapning kan du ta till exempel h1- och h2- titlarna, och resultatet skulle bli ungefär så här:

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

Du kan kontrollera att den hämtade informationen motsvarar den senaste artikeln i Baeldung:

6. Vad sägs om AJAX?

AJAX-funktioner kan vara ett problem eftersom HtmlUnit vanligtvis hämtar sidan innan AJAX-samtalen har avslutats. Många gånger behöver du dem för att testa din webbplats ordentligt eller för att hämta de data du vill ha. Det finns några sätt att hantera dem:

  • Du kan använda webClient.setAjaxController (ny NicelyResynchronizingAjaxController ()) . Detta synkroniserar samtal som utförs från huvudtråden och dessa samtal utförs synkront för att säkerställa att det finns ett stabilt tillstånd att testa.
  • När du går in på en sida i en webbapplikation kan du vänta några sekunder så det finns tillräckligt med tid för att låta AJAX-samtal avslutas. För att uppnå detta kan du använda webClient.waitForBackgroundJavaScript (MILLIS) eller webClient.waitForBackgroundJavaScriptStartingBefore (MILLIS) . Du bör ringa dem efter att ha hämtat sidan, men innan du arbetar med den.
  • Du kan vänta tills något förväntat villkor relaterat till genomförandet av AJAX-samtalet är uppfyllt. Till exempel:
for (int i = 0; i < 20; i++) { if (condition_to_happen_after_js_execution) { break; } synchronized (page) { page.wait(500); } }
  • Istället för att skapa en ny WebClient () , som standard är den bäst stödda webbläsaren, kan du prova andra webbläsare eftersom de kanske fungerar bättre med dina JavaScript- eller AJAX-samtal. Till exempel kommer detta att skapa en webClient som använder en Chrome-webbläsare:
WebClient webClient = new WebClient(BrowserVersion.CHROME);

7. Ett exempel med våren

Om vi ​​testar vår egen vårapplikation blir det lite enklare - vi behöver inte längre ha en server som körs .

Låt oss implementera en mycket enkel exempelapp: bara en kontroller med en metod som tar emot en text och en enda HTML-sida med ett formulär. Användaren kan mata in en text i formuläret, skicka in formuläret, och texten visas nedanför det formuläret.

I det här fallet använder vi en Thymeleaf-mall för den HTML-sidan (du kan se ett fullständigt Thymeleaf-exempel här):

@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); } }

Nyckeln här bygger WebClient- objektet med MockMvcWebClientBuilder från WebApplicationContext . Med WebClient kan vi få den första sidan i navigeringen (se hur den serveras av localhost ) och börja surfa därifrån.

Som du kan se analyserar testet formuläret ett meddelande (i ett fält med ID-meddelande), skickar formuläret och på den nya sidan hävdar det att den mottagna texten (fältet med ID "mottagen") är samma text som vi skickade in.

8. Slutsats

HtmlUnit är ett utmärkt verktyg som låter dig testa dina webbapplikationer enkelt, fylla i formulärfält och skicka in dem precis som om du använde webben i en webbläsare.

Den integreras sömlöst med Spring 4, och tillsammans med Spring MVC Test Framework ger de dig en mycket kraftfull miljö för att göra integrationstester på alla dina sidor även utan en webbserver.

Med HtmlUnit kan du också automatisera alla uppgifter som är relaterade till webbläsning, såsom att hämta, analysera, lagra och analysera data (webbskrapning).

Du kan få koden över på Github.