Селенид поддерживает Украину
На дворе декабрь, и в сегодняшнем посте рождественского календаря Selenide мы поговорим о том, какие возможности для скачивания файлов есть в Selenide.
UPD
Ниже описаны только два способа скачивания — HTTPGET и PROXY . Позже появился третий способ FOLDER . Возможно, вам нужен как раз он, если у вашей ссылки нет атрибута href , и прокси у вас не заводится.
Как я могу скачать файл в моём тесте?
В какой-то момент нашей карьеры каждый из нас сталкивается с необходимостью скачать какой-то файл в тесте.
Как мы помним, в Selenium это было непросто, потому что для разных браузеров требуются разные настройки.
Например, вот так выглядит создание профиля Firefox с нужными настройками:
profile.setPreference("browser.download.dir", downloadPath); profile.setPreference("browser.download.folderList", 2); profile.setPreference("browser.download.manager.showWhenStarting", false); profile.setPreference("browser.helperApps.alwaysAsk.force", false); profile.setPreference("browser.helperApps.neverAsk.saveToDisk", mimeTypes); profile.setPreference("browser.download.manager.focusWhenStarting",false); profile.setPreference("browser.download.manager.useWindow", false); profile.setPreference("browser.download.manager.showAlertOnComplete", false); profile.setPreference("pdfjs.disabled", true);
А в Selenide
Проблема решается гораздо проще — методом $.download() .
Чтобы скачать файл, в Selenide достаточно просто вызвать метод:
File report = element.download();
И Selenide автоматически сделает всё, что надо. Вам не придётся возиться со всплывающим окошком, которое спрашивает, куда сохранить файл, и потом закрывать его.
Selenide сохранит скачанный файл в папку build/reports/tests . Это та же папка, где Gradle генерирует результаты прогона тестов, так что их как раз удобно видеть вместе.
Конечно, поменять эту папку тоже можно:
Configuration.downloadsFolder = desired location for downloaded files>;
НО:
Таким образом можно скачивать файлы только со ссылкой с атрибутом “href”.
Но что, если у меня ссылки с атрибутом “href”? Так бывает, например, когда файл скачивается в результате сабмита формы. В этом случае можно скачивать файлы с помощью встроенного в селенид прокси-сервера.
Для начала нам нужно включить его (т.к. он по умолчанию выключен):
Configuration.proxyEnabled = true; Configuration.fileDownload = PROXY;
После этого мы снова можем вызывать метод $.download() , но теперь он стал более могущественным и не требует наличия атрибута “href”:
File report = element.download();
Хозяйке на заметку:
Не забудьте увеличить таймаут, если собираетесь скачивать файл большого размера.
Файл будет скачан в папку по умолчанию (что-то типа C:\downloads and settings\downloads ).
Таким образом, скачанный файл окажется в двух местах: c:\downloads. и build/reports/tests .
Если это для вас проблема, можете в конце теста удалить ненужную папку, чтобы очистить место на диске:
FileUtils.deleteDirectory(new File(папка, подлежащая удалению>));
Узнать подробнее про механизмы скачивания файлов можно тут.
Maciej Grymuza (figrym@gmail.com)
Единственно верный способ загружать и скачивать файлы в Selenium тестах

Selenium WebDriver создавался как кросс-платформенный инструмент для управления веб браузерами. И вот уже почти 14 лет он делает эту работу очень и очень хорошо. Впрочем, автотесты из реального мира создают ситуации, в которых Selenium бессилен. Например, по сценарию нужно загрузить или скачать какой-либо файл. После нажатия кнопки «Загрузить» или «Скачать», поверх окна браузера появляется окно файлового менеджера операционной системы к которому Selenium уже не имеет доступа. Тест останавливается.
Я слышал рекомендации использовать утилиты типа AutoIt или Sikuli для работы с такими системными окнами. Мой совет — никогда так не делайте, это порочная практика, которая приводит к нестабильным тестам:
- Такое решение не кросс-платформенное. Приходится изобретать свой велосипед для каждой новой операционной системы.
- Хрупкое. Нет гарантии, что скрипт будет работать корректно если на машине открыто несколько браузеров.
- Это делает невозможным использование headless режима браузера
Меня зовут Ярослав Пернеровский. Я уже 15 лет в тестировании и около 8 лет в автоматизации. Сейчас я расскажу как нужно правильно обрабатывать такие ситуации.
Если очень кратко
Все сложности с окнами операционной системы решаются довольно прямолинейно — надо сделать так, чтобы эти окна не появлялись и не мешали работе браузера.
Загрузка файла на сервер
В этом случае все просто, даже банально. Чтобы проблема не возникала — не нужно нажимать на кнопку «Загрузить». Вместо этого лучше поискать на странице элемент, который является файловым полем ввода (специальный input с типом file ) и с помощью метода sendKeys() «напечатать» в него абсолютный путь к нужному файлу:
By fileInput = By.cssSelector("input[type=file]"); String filePath = "/home/selenium/files/upload.txt"; driver.findElement(fileInput).sendKeys(filePath);
Это все. Дальше Selenium все сделает за вас. В любой операционной системе. В любом режиме браузера. После выполнения этого метода, сразу же, без лишних вопросов, начнется загрузка файла.
Что, если загрузка не началась? Возможно, вы пишите не в то поле, так как в DOM дереве присутствует несколько полей нужного типа. Это легко проверить в консоли браузера командой $$(«input[type=file]»)

Надо помнить, что метод findElement() возвращает самый первый элемент из найденных. Это не всегда может быть то что нужно. Следует более точно специфицировать локатор, чтобы он указывал на правильное поле. Тут надо поэкспериментировать, но в результате все заработает как надо.

Если Selenium продолжает ругаться
В угоду красивому дизайну, разработчики часто делают файловое поле скрытым. В таких случаях, Selenium ругается на то, что не может работать с невидимым элементом. Довольно прямолинейное решение — надо сделать поле видимым. Об этом хорошо написал Алексей Баранцев (barancev) в своем блоге. После таких манипуляций, никаких проблем с загрузкой быть не должно.
Скачивание файла с сервера
Если с загрузкой все абсолютно понятно, то скачивание файла уже не так однозначно. Современные браузеры по-умолчанию не спрашивают куда сохранять файл, а просто сохраняют в системную папку Downloads, а так как Selenium запускает браузеры с чистыми настройками и изолированными профилями (кроме Internet Explorer), то простое нажатие на «Скачать» начнет скачивание файла без открытия окна проводника.
Хотя, даже в таком случае, бывают внезапные уточняющие диалоги уже от самого браузера:

Это решается таким же способом, как и с загрузкой файла. Не надо нажимать никаких кнопок. Вместо этого давайте заглянем в код:

Как видно, кнопка реализована в виде ссылки. Атрибут href содержит путь к нужному файлу на сервере. Это идеальный вариант, так как все что нужно, это вытащить ссылку и скачать файл с помощью любого http клиента. Например для Java это выглядит следующим образом:
//Get download link String downloadLink = driver .findElement(By.cssSelector("main#content a.btn")) .getAttribute("href"); //Set file to save File fileToSave = new File("/path/to/file.zip"); //Download file using default org.apache.http client CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(downloadLink); HttpResponse response = httpClient.execute(httpGet, new BasicHttpContext()); //Save file on disk copyInputStreamToFile(response.getEntity().getContent(), fileToSave);
Загрузка файла через http
Конечно, для корректной загрузки через http, надо написать чуть более сложный код. Ведь нужно передавать http заголовки и куки текущей сессии браузера, обрабатывать ошибки и прочее. Полный код реализации такого механизма можно подсмотреть в исходниках библиотеки Selenide. Нужный класс называется DownloadFileWithHttpRequest.
К сожалению, не всегда бывает так просто. Случается, что ссылка для скачивания генерируется с помощью JavaScript и ее сложно получить в чистом виде. Тогда, без нажатия на кнопку уже не обойтись. Хорошая новость в том, что окошки операционной системы открываются не после нажатия на кнопку, а уже когда браузер получает серверный ответ, в котором содержится информация для сохранения на диск. Все что нам нужно сделать, это перехватить этот ответ и подменить метод сохранения из браузера на свой. Звучит просто, но на деле это требует установки прокси-сервера между браузером и настоящим бекендом. К счастью, существуют специальные прокси, которые прекрасно работают в связке с Selenium. Например современный BrowserUpProxy или классический BrowserMobProxy.
Реализация этого метода довольно громоздкая, но работающий пример можно найти в уже знакомом проекте Selenide. За это отвечает класс DownloadFileWithProxyServer.
В целом, этот способ самый надежный, но и он не лишен недостатков. Установленный прокси нарушает работу https, а это может повлиять на поведение тестируемого приложения.
В общем случае, надо хорошо подумать, что именно тестируется и действительно ли для этого нужно скачивать файлы. Если можно обойтись без скачивания, то лучше обойтись. Если нет — выбирайте самый простой способ из вышеописанных.
Заключение
Чтобы тесты оставались стабильными, надо убирать факторы, которые делают их хрупкими. Диалоговые окна операционной системы, это один из таких факторов. В следующих статьях я планирую раскрыть другие важные аспекты, которые сильно влияют на стабильную работу Selenium тестов. Слушайте подкаст QA Guild и хорошей вам автоматизации.
- selenium-webdriver
- тестирование веб-приложений
- автоматизация тестирования
- Тестирование IT-систем
- Тестирование веб-сервисов
Можно ли проверить загрузку файлов с помощью selenium и java?
Как проверить загрузку файлов (на компьютер пользователя) с помощью selenium и java? Без сторонних программ.
- Вопрос задан более двух лет назад
- 1185 просмотров
Комментировать
Решения вопроса 0
Ответы на вопрос 1
QA Engineer
Можно воспользоваться Selenide:
Метод $.download()
Если завершился успешно, значит твой файл скачался. Дальше уже можно проверить, что внутри файла, но это уже за рамками вопроса.
Есть ещё статья на Хабре, как это выполнить на Selenium: https://m.habr.com/ru/post/497922/
Ответ написан более двух лет назад
Комментировать
Нравится Комментировать
Ваш ответ на вопрос
Войдите, чтобы написать ответ

- Android
- +2 ещё
Почему при сворачивание приложения оно не развёртывается?
- 1 подписчик
- 10 часов назад
- 31 просмотр
Эффективные UI-тесты на Selenide
Канун Нового Года — время чудес. В преддверии нового года мы все вспоминаем год уходящий и строим планы на следующий. И надеемся, что все проблемы останутся в прошлом, а в новом году случится чудо, и мы заживём по-новому.
Какой же Java разработчик не мечтает о чуде, которое осенит его и позволит стать Самым Крутым На Свете Java Программистом.
Хорошие новости: я хочу рассказать как раз о таком чуде.
Имя ему — автоматические тесты!
Фу, тесты?
Да. Настоящим мастером своего дела вас сделают не чудо-фреймворки, не микро/пико/нано сервисы, а дисциплина. Дисциплина, которая говорит, что программист может считать дело законченным не тогда, когда код готов, а тогда, когда к нему написаны и запущены автоматические тесты. И если с юнит-тестами всё более-менее ясно, то UI-тесты пока остаются для разработчиков тёмным лесом.
Да ну, это же нудно?
О нет, поверьте мне! Написание грамотных автотестов — это отличный челлендж, тут есть над чем пораскинуть мозгами. И это может быть очень весело и интересно. Только надо использовать правильные инструменты.
Правильный инструмент для написания UI-тестов — это:
Selenide
Selenide — это библиотека для написания лаконичных и стабильных UI тестов с открытым исходным кодом.
Selenide — идеальный выбор для разработчиков, потому что у неё очень низкая кривая обучения. Вам не придётся заморачиваться со всеми этими техническими подробностям, на которые обычно тестировщики-автоматизаторы тратят так много времени: нюансы работы с браузерами, типичные проблемы с таймингом и аяксом.
Посмотрим, как выглядит простенький тест на Selenide:
public class GoogleTest @Test public void user_can_search_everything_in_google() open("http://google.com/ncr"); $(By.name("q")).val("selenide").pressEnter(); $$("#ires .g").shouldHave(size(10)); $("#ires .g").shouldBe(visible).shouldHave( text("Selenide: concise UI tests in Java"), text("selenide.org")); > >
(естественно, вместо Google здесь будет ваше веб-приложение)
Что здесь происходит?
- Вы открываете браузер всего-навсего одной командой open(url)
- Вы ищете элемент на странице командой $ .
Вы можете найти элемент по имени, ID, CSS селектору, атрибуту, xpath и даже по тексту. - Вы совершаете некие действия с элементом: в данном случае вводите текст командой val() и нажимаете ввод с помощью команды pressEnter() .
- Вы проверяете результат: ищете все результаты поиска с помощью $$ (она возвращает коллекцию элементов). Вы проверяете размер и содержимое коллекции.
Этот тест легко читается, не правда ли?
Этот тест легко пишется, не правда ли?
А главное, этот тест легко запускается. Убедитесь сами:
Погружаемся глубже
Конечно, в жизни не всё так просто. Написание автотестов подразумевает кучу проблем, ведь не зря разработчики так их боятся — больше, чем любого наисложнейшего фреймворка или технологии.
Но и здесь Selenide облегчает нашу жизнь, решая большинство этих проблем из коробки.
Давайте рассмотрим типичные проблемы UI-тестов подробнее.
Проблемы с аяксом и таймаутами
В наше время веб-приложения все сплошь динамические. Каждый кусочек приложения может быть нарисован/изменён динамически в любой момент времени. Это создаёт проблемы для автоматических тестов. Тест, который ещё вчера был зелёным, может внезапно стать красным безо всяких изменений в коде. Просто потому, что браузер сегодня встал не с той ноги и запустил вон тот javascript чуточку медленнее, и тест успел кликнуть кнопочку раньше, чем она до конца отрисовалась.
Это прям вечная проблема у всех. Поэтому автоматизаторы пихают везде “слипы”.
Тем более удивительно, насколько простым и надёжным способом Selenide решает эту проблему.
Если коротко, в Selenide каждый метод умеет немножко подождать, если надо. Люди называют это “умными ожиданиями”.
Когда вы пишете
$("#menu").shouldHave(text("Hello"));
Selenide проверит, существует ли элемент с И если нет, Selenide чуть-чуть подождёт, проверит ещё. Потом ещё подождёт. И только когда элемент появится, Selenide проверит, что у него нужный текст.
Конечно, нельзя ждать вечно. Поэтому Selenide ждёт не больше 4 секунд. Естественно, этот таймаут можно настраивать.
Не сделает ли это мои тесты медленными?
Нет, не сделает. Selenide ждёт, только если надо. Если элемент изначально присутствует на странице — Selenide не ждёт. Если элемент появился через 300 мс — Selenide ждёт только 300 мс. Это именно то, что вам нужно.
Множество встроенных проверок
А что ещё вы можете проверять на странице, помимо текста? Довольно много всего.
Например, вы можете проверить, что элемент видимый ( visible ). Если пока нет, Selenide подождёт до 4 секунд.
$(".loading_progress").shouldBe(visible);
Вы можете даже проверить, что элемент не существует. Если элемент всё же найден, Selenide предположит, что он вот-вот пропадёт и подождёт до 4 секунд.
$(By.name("gender")).should(disappear);
Вы можете делать несколько проверок в одной строке (т.н. “fluent API” и “method chain”), что сделает ваши тесты ещё более лаконичными:
$("#menu") .shouldHave(text("Hello"), text("John!")) .shouldBe(enabled, selected);
Коллекции
Selenide позволяет вам очень удобно работать с коллекциями элементов. Вы можете проверять сразу множество элементов в одной строке.
Например, вы можете проверить, что на странице ровно N таких-то элементов:
$$(".error").shouldHave(size(3));
Вы можете отфильтровать подмножество элементов:
$$("#employees tbody tr") .filter(visible) .shouldHave(size(4));
Вы можете проверить тексты элементов. В большинстве случаев этого достаточно, чтобы проверить целую таблицу или строку в таблице:
$$("#employees tbody tr").shouldHave( texts( "John Belushi", "Bruce Willis", "John Malkovich" ) );
Скачивание/закачивание файлов
С Selenide закачивать файлы предельно просто:
$("#cv").uploadFile(new File("cv.doc"));
И вы даже можете закачать несколько файлов разом:
$("#cv").uploadFile( new File("cv1.doc"), new File("cv2.doc"), new File("cv3.doc") );
И скачивание файлов тоже крайне просто:
File pdf = $(".btn#cv").download();
Тестирование “динамичных” веб-приложений
Некоторые веб-фреймворки (такие как GWT) генерируют совершенно нечитаемый HTML, не поддающийся анализу. Там нет постоянных ID, имён или классов.
Это прям вечная проблема у всех. Поэтому автоматизаторы пихают везде длиннющие “xpath” и вынуждены их поддерживать до конца жизни.
Чтобы решить эту проблему, Selenide предлагает искать элементы по тексту.
import static com.codeborne.selenide.Selectors.*; $(byText("Привет, октябрята!")) // находит элемент по тексту целиком .shouldBe(visible); $(withText("тябр")) // находит элемент по подстроке .shouldHave(text("Привет, октябрята!"));
Вопреки распространённому мнению, поиск элементов по тексту — не такая уж плохая идея. Между прочим, именно так ищет элементы реальный пользователь. Он не ищет элементы по ID или классу, и уж тем более не по XPATH. Он ищет по тексту. (ну, ещё по цвету, но это труднее поддаётся автоматизации).
Ещё в Selenide есть несколько полезных методов для поиска дочерних или родительских элементов. Это позволяет вам навигировать между элементами без опознавательных знаков.
$("td").parent() $("td").closest("tr") $(".btn").closest(".modal") $("div").find(By.name("q"))
Например, вы можете найти ячейку в таблице по тексту, затем найти содержащую её строку tr и найти в этой строке кнопку “Save”:
$("table#employees") .find(byText("Joshua")) .closest("tr.employee") .find(byValue("Save")) .click();
PageObject
Когда один и тот же элемент или страница используется во многих тестах, имеет смысл вынести логику страницы в отдельный класс. Такой класс называется Page Object, и их тоже очень удобно делать с Selenide.
Приведённый выше пример гугла можно переделать на page object таким образом:
@Test public void userCanSearch() GooglePage page = open("http://google.com/ncr", GooglePage.class); SearchResultsPage results = page.searchFor("selenide"); results.getResults().shouldHave(size(10)); results.getResult(0).shouldHave(text("Selenide: concise UI tests in Java")); >
Page Object для страницы поиска гугл:
public class GooglePage public SearchResultsPage searchFor(String text) $(By.name("q")).val(text).pressEnter(); return page(SearchResultsPage.class); > >
И для страницы результатов поиска:
public class SearchResultsPage public ElementsCollection getResults() return $$("#ires .g"); > public SelenideElement getResult(int index) return $("#ires .g", index); > >
Но хочу обратить ваше внимание, что UI-тестов должно быть мало. По той простой причине, что это всё-таки браузер, аякс, javascript, а всё это сравнительно медленно и нестабильно. Напишите один-два UI-теста, которые проверят, что приложение в целом работает: страничка открывается, текст отрисовывается, кнопки нажимаются, JavaScript не грохается.
А всевозможные комбинации и редкие случаи обязательно проверяйте с помощью модульных тестов.
Типичная ошибка — проверять всё через UI. Этим особенно страдают тестировщики в тех компаниях, где разработчики не пишут модульных тестов. Бедным тестировщикам просто ничего не остаётся, кроме как городить огромную неповоротливую кучу медленных и нестабильных UI-тестов и впрягаться в их пожизненную поддержку.
Но ты ж программист! Не заставляй людей мучаться.
… и много других полезняшек
В Selenide есть ещё много функций, таких как:
$("div").scrollTo(); $("div").innerText(); $("div").innerHtml(); $("div").exists(); $("select").isImage(); $("select").getSelectedText(); $("select").getSelectedValue(); $("div").doubleClick(); $("div").contextClick(); $("div").hover(); $("div").dragAndDrop() zoom(2.5); .
мы не сможем их все здесть описать. Но хорошая новость в том, что вам не нужно всё это запоминать. Просто наберите $ , точку и начните писать примерно, что вы хотите. Например “val” или “enter”. И посмотрите, какие варианты предложит ваша IDE.
Используйте мощь IDE! Не засоряйте голову деталями и сконцентрируйтесь на бизнес-логике.

Сделаем мир лучше
У верю, что мир станет лучше, когда все разработчики будут писать автоматические тесты для своего кода. Когда разработчики будут спокойно вставать в 17:00 и идти к своим детям, не боясь, что они что-то сломали своими изменениями.
Поверьте мне, я чувствую себя уверенно оттого, что пока я ходил за кофе, мои тесты уже проверили мой код. И я точно знаю, что то, что я сдаю в тестирование — работает.
Давайте сделаем мир лучше с помощью автоматических тестов! Будьте уверены в своём софте, и вам не придётся скрещивать пальцы на удачу перед каждым релизом.