четверг, 11 июня 2009 г.

htmlunit WebRequestSettings - встали и вышли...

Добрый день, дорогие блогочитатели.
Мы снова с Вами. Борьба с некачественным софтом продолжается. Предлагаю сегодня рассмотреть интересную багу, найденную Вашим покорным слугой, в инструменте для автоматизированного тестирования. На этот раз это - HtmlUnit.
Итак, багу в студию (под звук фанфар в зал вносят тело клиента)...

htmlunit-2.5

Короткое описание
При клике на линк и открытии страницы теряются установленные первоначально параметры запроса (WebRequestSettings)


Шаги для воспроизведения
1. Пишем следующий код
WebClient client = new WebClient();
client.setJavaScriptEnabled(false);
WebRequestSettings settings = new WebRequestSettings(new URL("http://www.protesting.ru"));
settings.setCharset("utf-8");
client.getPage(settings);

HtmlPage page = (HtmlPage) client.getCurrentWindow().getEnclosedPage();
List list = page.getAnchors();
for (int i = 0; i < list.size(); i++) {
HtmlAnchor htmlAnchor = (HtmlAnchor) list.get(i);
if (htmlAnchor.getHrefAttribute().equals("./automation/")) {
try {
page = htmlAnchor.click();
break;
} catch (IOException e) {
e.printStackTrace();
}
}
}
String title = page.getTitleText();
System.out.println(title);

2. Выполняем его

Результат
Про Те�тинг - �втоматиЕированное те�тирование программного обе�печени� (Software Test Automation)

Ожидаемый результат
Про Тестинг - Автоматизированное тестирование программного обеспечения (Software Test Automation)

Примечание
Копнул немного глубже, и могу поделиться тем, что я увидел внутри.
В нашей имплементации, мы создаем WebRequestSettings setting и в нем явно указываем кодировку settings.setCharset("utf-8"). WebClient открывает страницу и уже знает, что она будет идти в кодировке utf-8.
Если мы не будем создавать свои WebRequestSettings, то htmlunit выставит charset по умолчанию (charset_ = TextUtil.DEFAULT_CHARSET = "ISO-8859-1"), и тогда уже начиная с первой страницы будут грабли.

Дальше интереснее.
Мы получили страницу с явно указаной кодировкой UTF-8 и делаем клик по ссылке, что явно должно подразумевать, что параметры запроса не изменились, делаем клик и получаем страницу с крокозябрами вместо русского текста.
Идем в класс HtmlAnchor и видим там следующий код:
protected Page doClickAction(final Page defaultPage, final String hrefSuffix) throws IOException {
final String href = getHrefAttribute() + hrefSuffix;

if (mainLog_.isDebugEnabled()) {
mainLog_.debug(
"do click action in window '"
+ defaultPage.getEnclosingWindow().getName()
+ "', using href '" + href + "'");
}

if (href.length() > 0 && !href.startsWith("#")) {
final HtmlPage page = (HtmlPage) getPage();
if (TextUtil.startsWithIgnoreCase(href, JAVASCRIPT_PREFIX)) {
return page.executeJavaScriptIfPossible(
href, "javascript url", getStartLineNumber()).getNewPage();
}
final URL url = page.getFullyQualifiedUrl(href);
final WebRequestSettings settings = new WebRequestSettings(url);
settings.addAdditionalHeader("Referer", page.getWebResponse().getRequestUrl().toExternalForm());
if (mainLog_.isDebugEnabled()) {
mainLog_.debug(
"Getting page for " + url.toExternalForm()
+ ", derived from href '" + href
+ "', using the originating URL "
+ page.getWebResponse().getRequestUrl());
}
return page.getWebClient().getPage(
page.getEnclosingWindow(),
page.getResolvedTarget(getTargetAttribute()),
settings);
}
return defaultPage;
}

О ужас:
final WebRequestSettings settings = new WebRequestSettings(url);

WebRequestSettings пересоздаются при клике на ссылке и все наши настройки теряются.

Немного поиграв, я заменил эту строку на следующие:
final WebRequestSettings settings = page.getWebResponse().getRequestSettings();
settings.setUrl(url);

И перезапустил код из примера.

Результат:
Про Тестинг - Автоматизированное тестирование программного обеспечения (Software Test Automation)


Что и требовалось ожидать.

Бага в саппорт htmlunit написана, ждем ответа!
https://sourceforge.net/tracker/?func=detail&aid=2804850&group_id=47038&atid=448266

PS Если кто знает, как в htmlunit можно глобально установить параметры кодировки запроса и ответа от сервера, буду премного благодарен.

Оставайтесь с нами,
Всегда Ваш - Я

Да хранит Вас WWW.

3 комментария:

А.Б. комментирует...

Всегда приятно получить следущие комменты от разрабтчиков инструментов, на которые вы пишите баги:
------------
Message:
OK, it looks like we're not checking the meta tags for charset info. I'm going to implement the HTML5 character sniffing algorithm [1] in HU (step 4 is the part we don't have), which should take care of this. Will keep you
updated.

[1]
http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#determining-the-character-encoding
------

Так что не все еще потеряно...

А.Б. комментирует...

В продолжение...

Фикс сделали и сказали где взять, но как и всегда не до конца все починили, НО при этом сразу закрыли багу, не дождавшись моих комментов :)

:)

А.Б. комментирует...

Итак, бага зафикшена и выложена во временное "хранилище" :) надеюсь, что она попадет в следующий релиз.

Для тех кому понадобится данный фикс, его можно найти здесь:
----
Fixed in SVN. You can try the snapshot build at
http://build.canoo.com/htmlunit/artifacts if you don't want to wait for the
next release.
----

Условия копирования публикаций:

Все публикации в данном блоге являются частной собственностью авторов. Любое копирование информации допускается только при условии указания имени автора и активной ссылки на источник.