Использование Selenium 2 дает вам некоторый пробег. Я использую Selenium 2 WebDriver в сочетании с вариацией Selenium DSL, найденной здесь .
Первоначально я изменил DSL, чтобы было немного проще работать с REPL (см. Ниже). Однако одна из самых больших проблем при создании подобных тестов заключается в том, что они быстро становятся недействительными, а затем становятся кошмаром для обслуживания.
Позже я начал создавать класс-оболочку для каждой страницы в приложении, с удобными операциями, отображающими событие, которое будет отправлено на эту страницу, в базовые вызовы WebDriver
. Таким образом, всякий раз, когда меняется подчиненная страница, мне просто нужно изменить оболочку страницы, а не весь сценарий. При этом мои тестовые сценарии теперь выражаются в терминах вызовов для отдельных упаковщиков страниц, где каждый вызов возвращает оболочку страницы, отражающую новое состояние пользовательского интерфейса. Кажется, получилось довольно хорошо.
Я склонен строить свои тесты с помощью FirefoxDriver
, а затем перед переносом теста в нашу среду QA проверить, дает ли драйвер HtmlUnit
сравнимые результаты. Если это так, то я запускаю тест, используя драйвер HtmlUnit
.
Это была моя оригинальная модификация Selenium DSL:
/**
* Copied from [[http://comments.gmane.org/gmane.comp.web.lift/44563]], adjusting it to no longer be a trait that you need to mix in,
* but an object that you can import, to ease scripting.
*
* With this object's method imported, you can do things like:
*
* {{"#whatever"}}: Select the element with ID "whatever"
* {{".whatever"}}: Select the element with class "whatever"
* {{"%//td/em"}}: Select the "em" element inside a "td" tag
* {{":em"}}: Select the "em" element
* {{"=whatever"}}: Select the element with the given link text
*/
object SeleniumDsl {
private def finder(c: Char): String => By = s => c match {
case '#' => By id s
case '.' => By className s
case '$' => By cssSelector s
case '%' => By xpath s
case ':' => By name s
case '=' => By linkText s
case '~' => By partialLinkText s
case _ => By tagName c + s
}
implicit def str2by(s: String): By = finder(s.charAt(0))(s.substring(1))
implicit def by2El[T](t: T)(implicit conversion: (T) => By, driver: WebDriver): WebElement = driver / (conversion(t))
implicit def el2Sel[T <% WebElement](el: T): Select = new Select(el)
class Searchable(sc: SearchContext) {
def /[T <% By](b: T): WebElement = sc.findElement(b)
def /?[T <% By](b: T): Box[WebElement] = tryo(sc.findElement(b))
def /+[T <% By](b: T): Seq[WebElement] = sc.findElements(b)
}
implicit def scDsl[T <% SearchContext](sc: T): Searchable = new Searchable(sc)
}