Inleiding tot HtmlUnit

1. Inleiding

In dit artikel introduceren we HtmlUnit, een tool waarmee we, simpel gezegd, interactie met en test een HTML-site programmatisch, met behulp van JAVA API's.

2. Over HtmlUnit

HtmlUnit is een GUI-loze browser - een browser die bedoeld is om programmatisch te worden gebruikt en niet rechtstreeks door een gebruiker.

De browser ondersteunt JavaScript (via de Mozilla Rhino-engine) en kan zelfs worden gebruikt voor websites met complexe AJAX-functionaliteiten. Dit alles kan worden gedaan door een typische GUI-gebaseerde browser zoals Chrome of Firefox te simuleren.

De naam HtmlUnit zou je kunnen doen denken dat het een testraamwerk is, maar hoewel het zeker kan worden gebruikt om te testen, kan het zoveel meer dan dat.

Het is ook geïntegreerd in Spring 4 en kan naadloos worden gebruikt in combinatie met het Spring MVC Test-framework.

3. Download en Maven afhankelijkheid

HtmlUnit kan worden gedownload van SourceForge of van de officiële website. Je kunt het ook opnemen in je bouwtool (zoals onder andere Maven of Gradle), zoals je hier kunt zien. Dit is bijvoorbeeld de Maven-afhankelijkheid die u momenteel in uw project kunt opnemen:

 net.sourceforge.htmlunit htmlunit 2.23 

De nieuwste versie is hier te vinden.

4. Webtesten

Er zijn veel manieren waarop u een webtoepassing kunt testen - de meeste daarvan hebben we hier op de site op een bepaald moment behandeld.

Met HtmlUnit kunt u de HTML van een site direct parseren, ermee communiceren zoals een normale gebruiker dat vanuit de browser zou doen, JavaScript en CSS-syntaxis controleren, formulieren indienen en de antwoorden parseren om de inhoud van de HTML-elementen te zien. Allemaal met pure Java-code.

Laten we beginnen met een eenvoudige test: maak een Web cliënt en krijg de eerste pagina van de navigatie van www.baeldung.com:

privé WebClient webClient; @Before public void init () gooit Uitzondering {webClient = nieuwe WebClient (); } @After public void close () gooit uitzondering {webClient.close (); } @Test openbare ongeldig gegevenAClient_whenEnteringBaeldung_thenPageTitleIsOk () gooit Uitzondering HtmlPage-pagina = webClient.getPage ("/"); Assert.assertEquals ("Baeldung 

U kunt enkele waarschuwingen of fouten zien bij het uitvoeren van die test als onze website JavaScript- of CSS-problemen heeft. U moet ze corrigeren.

Soms, als u weet wat u doet (als u bijvoorbeeld ziet dat de enige fouten die u heeft afkomstig zijn uit JavaScript-bibliotheken van derden die u niet mag wijzigen), kunt u voorkomen dat deze fouten ervoor zorgen dat uw test mislukt. setThrowExceptionOnScriptError met false:

@Test openbare leegte gegevenAClient_whenEnteringBaeldung_thenPageTitleIsCorrect () gooit Exception Java, Spring en Web Development tutorials ", page.getTitleText ()); 

5. Webschrapen

U hoeft HtmlUnit niet alleen voor uw eigen websites te gebruiken. Het is tenslotte een browser: u kunt het gebruiken om door elk gewenst internet te navigeren, gegevens te verzenden en op te halen als dat nodig is.

Het ophalen, ontleden, opslaan en analyseren van gegevens van websites is het proces dat bekend staat als webscraping en HtmlUnit kan u helpen met het ophalen en ontleden van onderdelen.

Het vorige voorbeeld laat zien hoe we elke website kunnen betreden en erdoorheen kunnen navigeren, waarbij we alle gewenste informatie ophalen.

Laten we bijvoorbeeld naar het volledige archief met artikelen van Baeldung gaan, naar het laatste artikel navigeren en de titel (eerst

label). Voor onze test is dat voldoende; maar als we meer informatie willen opslaan, kunnen we bijvoorbeeld de koppen (all

tags), zodat u een idee heeft van waar het artikel over gaat.

Het is gemakkelijk om elementen op basis van hun ID te krijgen, maar over het algemeen is het handiger om een ‚Äč‚Äčelement te vinden als u een element moet vinden gebruik XPath-syntaxis. Met HtmlUnit kunnen we het gebruiken, dus we zullen het gebruiken.

@Test openbare leegte gegevenBaeldungArchive_whenRetrievingArticle_thenHasH1 () gooit Uitzondering {webClient.getOptions (). SetCssEnabled (false); webClient.getOptions (). setJavaScriptEnabled (false); String url = "/ full_archive"; HtmlPage-pagina = webClient.getPage (url); String xpath = "(// ul [@ class = 'auto-maandlijst'] / li) [1] / a"; HtmlAnchor latestPostLink = (HtmlAnchor) page.getByXPath (xpath) .get (0); HtmlPage postPage = latestPostLink.click (); Lijst h1 = (Lijst) postPage.getByXPath ("// h1"); Assert.assertTrue (h1.size ()> 0); } 

Merk eerst op hoe - in dit geval zijn we niet geïnteresseerd in CSS of JavaScript en willen we alleen de HTML-lay-out parseren, dus hebben we CSS en JavaScript uitgeschakeld.

Bij een echte webscraping kunt u bijvoorbeeld de h1 en h2 titels, en het resultaat zou ongeveer als volgt zijn:

Java Web Weekly, uitgave 135 1. Lente en Java 2. Technisch en overpeinzingen 3. Stripverhalen 4. Keuze van de week

U kunt controleren of de opgehaalde informatie inderdaad overeenkomt met het laatste artikel in Baeldung:

6. Hoe zit het met AJAX?

AJAX-functionaliteiten kunnen een probleem zijn omdat HtmlUnit de pagina meestal zal ophalen voordat de AJAX-oproepen zijn voltooid. Vaak heb je ze nodig om je website goed te testen of om de gewenste data op te halen. Er zijn enkele manieren om hiermee om te gaan:

  • Je kunt gebruiken webClient.setAjaxController (nieuw NicelyResynchronizingAjaxController ()). Hierdoor worden oproepen opnieuw gesynchroniseerd die worden uitgevoerd vanuit de hoofdthread en deze oproepen worden synchroon uitgevoerd om ervoor te zorgen dat er een stabiele status is om te testen.
  • Wanneer u een pagina van een webtoepassing opent, kunt u enkele seconden wachten, zodat er voldoende tijd is om AJAX-oproepen te laten eindigen. Om dit te bereiken, kunt u gebruik maken van webClient.waitForBackgroundJavaScript (MILLIS) of webClient.waitForBackgroundJavaScriptStartingBefore (MILLIS). U moet ze bellen nadat u de pagina heeft opgehaald, maar voordat u ermee werkt.
  • U kunt wachten tot aan een verwachte voorwaarde met betrekking tot de uitvoering van de AJAX-oproep is voldaan. Bijvoorbeeld:
for (int i = 0; i <20; i ++) {if (condition_to_happen_after_js_execution) {break; } gesynchroniseerd (pagina) {page.wait (500); }}
  • In plaats van een nieuwe WebClient (), die standaard de best ondersteunde webbrowser is, probeer dan andere browsers, aangezien deze wellicht beter werken met uw JavaScript- of AJAX-oproepen. Hiermee wordt bijvoorbeeld een webClient gemaakt die een Chrome-browser gebruikt:
WebClient webClient = nieuwe WebClient (BrowserVersion.CHROME);

7. Een voorbeeld met de lente

Als we onze eigen Spring-applicatie testen, wordt het een beetje eenvoudiger - we hebben niet langer een draaiende server nodig.

Laten we een heel eenvoudige voorbeeld-app implementeren: alleen een controller met een methode die een tekst ontvangt, en een enkele HTML-pagina met een formulier. De gebruiker kan een tekst in het formulier invoeren, het formulier verzenden en de tekst wordt onder dat formulier weergegeven.

In dit geval gebruiken we een Thymeleaf-sjabloon voor die HTML-pagina (u kunt hier een volledig Thymeleaf-voorbeeld bekijken):

@RunWith (SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration (classes = {TestConfig.class}) openbare klasse HtmlUnitAndSpringTest {@Autowired private WebApplicationContext wac; privé WebClient webClient; @Before public void setup () {webClient = MockMvcWebClientBuilder .webAppContextSetup (wac) .build (); } @Test openbare leegte gegevenAMessage_whenSent_thenItShows () gooit uitzondering {String text = "Hallo wereld!"; HtmlPage-pagina; String url = "// localhost / bericht / showForm"; page = webClient.getPage (url); HtmlTextInput messageText = page.getHtmlElementById ("bericht"); messageText.setValueAttribute (tekst); HtmlForm form = page.getForms (). Get (0); HtmlSubmitInput submit = form.getOneHtmlElementByAttribute ("input", "type", "submit"); HtmlPage newPage = submit.click (); String ontvangenText = newPage.getHtmlElementById ("ontvangen") .getTextContent (); Assert.assertEquals (ontvangenText, tekst); }}

De sleutel hier is het bouwen van het Web cliënt object gebruiken MockMvcWebClientBuilder van de WebApplicationContext. Met de Web cliënt, kunnen we de eerste pagina van de navigatie krijgen (let op hoe deze wordt bediend door localhost), en begin vanaf daar te browsen.

Zoals u kunt zien, parseert de test het formulier, voert een bericht in (in een veld met ID "bericht"), verzendt het formulier en beweert op de nieuwe pagina dat de ontvangen tekst (veld met ID "ontvangen") de hetzelfde als de tekst die we hebben ingediend.

8. Conclusie

HtmlUnit is een geweldige tool waarmee u uw webtoepassingen eenvoudig kunt testen, formuliervelden kunt invullen en indienen alsof u het web in een browser gebruikt.

Het integreert naadloos met Spring 4, en samen met Spring MVC Test framework geven ze je een zeer krachtige omgeving om integratietests uit te voeren van al je pagina's, zelfs zonder een webserver.

Met HtmlUnit kunt u ook elke taak met betrekking tot surfen op het web automatiseren, zoals het ophalen, ontleden, opslaan en analyseren van gegevens (webscraping).

Je kunt de code op Github krijgen.