Въведение в HtmlUnit

1. Въведение

В тази статия ще представим HtmlUnit, инструмент, който ни позволява просто да кажем, да взаимодействаме и тестваме HTML сайт програмно, използвайки JAVA API .

2. Относно HtmlUnit

HtmlUnit е браузър без GUI - браузър, предназначен да се използва програмно, а не директно от потребител.

Браузърът поддържа JavaScript (чрез Mozilla Rhino engine) и може да се използва дори за уебсайтове със сложни AJAX функционалности. Всичко това може да се направи симулирайки типичен браузър, базиран на GUI като Chrome или Firefox.

Името HtmlUnit може да ви накара да мислите, че това е рамка за тестване, но въпреки че определено може да се използва за тестване, може да направи много повече от това.

Той също е интегриран в Spring 4 и може да се използва безпроблемно заедно с Spring MVC Test framework.

3. Изтегляне и зависимост на Maven

HtmlUnit може да бъде изтеглен от SourceForge или от официалния уебсайт. Също така можете да го включите във вашия инструмент за изграждане (като Maven или Gradle, наред с други), както можете да видите тук. Например това е зависимостта на Maven, която в момента можете да включите във вашия проект:

 net.sourceforge.htmlunit htmlunit 2.23  

Най-новата версия можете да намерите тук.

4. Уеб тестване

Има много начини, по които можете да тествате уеб приложение - повечето от които разгледахме тук на сайта в една или друга точка.

С HtmlUnit можете директно да анализирате HTML на даден сайт, да взаимодействате с него точно както нормален потребител от браузъра, да проверите синтаксиса на JavaScript и CSS, да изпратите формуляри и да анализирате отговорите, за да видите съдържанието на неговите HTML елементи. Всичко това, използвайки чист Java код.

Нека започнем с прост тест: създайте WebClient и вземете първата страница от навигацията на 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  

Можете да видите някои предупреждения или грешки при изпълнението на този тест, ако нашият уебсайт има проблеми с JavaScript или CSS. Трябва да ги поправите.

Понякога, ако знаете какво правите (например, ако видите, че единствените грешки, които имате, са от JavaScript библиотеки на трети страни, които не трябва да променяте), можете да предотвратите провала на тези грешки, като извикате setThrowExceptionOnScriptError с невярно :

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

5. Уеб изстъргване

Не е необходимо да използвате HtmlUnit само за собствените си уебсайтове. В края на краищата това е браузър: можете да го използвате, за да навигирате във всяка мрежа, която харесвате, да изпращате и извличате данни, ако е необходимо.

Извличането, анализирането, съхраняването и анализирането на данни от уебсайтове е процесът, известен като изстъргване на уеб и HtmlUnit може да ви помогне с извличането и анализирането на части.

Предишният пример показва как можем да влезем във всеки уебсайт и да се придвижваме през него, като извличаме цялата информация, която искаме.

Например, нека отидем до пълния архив със статии на Baeldung, отидете до последната статия и извлечете заглавието й (първо

таг). За нашия тест това ще бъде достатъчно; но ако искахме да съхраним повече информация, можехме например да извлечем заглавията (всички

тагове), като по този начин имате основна представа за какво става въпрос в статията.

Лесно е да получите елементи по техния идентификатор, но като цяло, ако трябва да намерите елемент, е по-удобно да използвате синтаксиса XPath . HtmlUnit ни позволява да го използваме, така че ще го направим.

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

Първо обърнете внимание как - в този случай ние не се интересуваме от CSS, нито JavaScript и просто искаме да анализираме HTML оформлението, така че изключихме CSS и JavaScript.

В истинско изрязване на мрежата можете да вземете например заглавията h1 и h2 и резултатът ще бъде нещо подобно:

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

Можете да проверите дали получената информация наистина отговаря на последната статия в Baeldung:

6. Ами AJAX?

Функционалностите на AJAX могат да бъдат проблем, тъй като HtmlUnit обикновено извлича страницата, преди AJAX повикванията да приключат. Много пъти се нуждаете от тях, за да завършите, за да тествате правилно уебсайта си или да извлечете желаните данни. Има няколко начина да се справите с тях:

  • 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.

Той се интегрира безпроблемно с Spring 4 и заедно с Spring MVC Test framework ви дават много мощна среда за извършване на тестове за интеграция на всички ваши страници дори без уеб сървър.

Също така, използвайки HtmlUnit, можете да автоматизирате всяка задача, свързана с сърфирането в мрежата, като извличане, анализиране, съхраняване и анализ на данни (изрязване в мрежата).

Можете да получите кода на Github.