大连网站排名系统,seog,无锡市梁溪区建设局网站,设计模板设置为本地模板Selenium是一组支持浏览器自动化的工具和库#xff0c;主要用于Web应用程序测试。 Selenium的组件之一是Selenium WebDriver#xff0c;它提供客户端库#xff0c;JSON有线协议#xff08;与浏览器驱动程序进行通信的协议#xff09;和浏览器驱动程序。 Selenium WebDrive… Selenium是一组支持浏览器自动化的工具和库主要用于Web应用程序测试。 Selenium的组件之一是Selenium WebDriver它提供客户端库JSON有线协议与浏览器驱动程序进行通信的协议和浏览器驱动程序。 Selenium WebDriver的主要优点之一是它受所有主要编程语言的支持并且可以在所有主要操作系统上运行。 在带有Selenium WebDriver的JUnit 5的这一部分中我将通过Selenium的内置PageFactory支持类来介绍Page Object模式的实现。 PageFactory提供了一种机制用于初始化任何声明使用FindBy批注注释的WebElement或ListWebElement字段的Page对象。 关于本教程 您正在阅读带有Selenium WebDriver的JUnit 5的第二部分-教程 。 本教程中的所有文章 第1部分– 从头开始设置项目–使用JUnit 5和Jupiter Selenium进行Gradle 第2部分– 使用Selenium内置的PageFactory实现Page Object Pattern 接下来的是 第3部分–改进项目配置–并行执行测试测试执行顺序参数化测试AssertJ等 该教程的源代码可以在Github上找到 介绍页面对象模式 我们将在以下位置为基于JavaScript的Todo应用程序创建测试 http : //todomvc.com/examples/vanillajs 。 该应用程序被创建为单页应用程序SPA并使用本地存储作为任务存储库。 可能实现的方案包括添加和编辑待办事项删除待办事项将单个或多个待办事项标记为已完成。 该实现将使用Page Object模式完成。 页面对象模式的目标是从实际测试中抽象出应用程序页面和功能。 页面对象模式提高了代码在测试和固定装置之间的可重用性但也使代码易于维护。 您可以在Martin Fowler的文章中了解有关此模式的更多信息 https : //martinfowler.com/bliki/PageObject.html 页面API或页面对象 我们将从将TodoMVC页面建模为Page Object的项目开始。 该对象将表示将在测试中使用的页面API。 可以使用接口对API本身进行建模。 如果查看以下界面的方法则会注意到这些方法只是页面上可用的用户功能。 用户可以创建待办事项 用户可以重命名待办事项 也可以删除待办事项 public interface TodoMvc { void navigateTo(); void createTodo(String todoName); void createTodos(String... todoNames); int getTodosLeft(); boolean todoExists(String todoName); int getTodoCount(); ListString getTodos(); void renameTodo(String todoName, String newTodoName); void removeTodo(String todoName); void completeTodo(String todoName); void completeAllTodos(); void showActive(); void showCompleted(); void clearCompleted(); } 上面的接口显然隐藏了所有实现细节但也没有将任何Selenium WebDriver详细信息公开给潜在的客户端在我们的情况下客户端测试方法。 实际上它与Selenium WebDriver无关。 因此从理论上讲我们可以针对不同的设备例如移动本机应用程序桌面应用程序和Web应用程序使用此页面的不同实现。 创建测试 定义了页面API后我们可以直接跳转到创建测试方法。 在确认API可用于创建测试之后我们将进行页面实现。 这种设计技术使您可以专注于应用程序的实际使用而不必太早进入实现细节。 创建了以下测试 ExtendWith (SeleniumExtension. class ) DisplayName ( Managing Todos DisplayName Managing Todos ) class TodoMvcTests { private TodoMvc todoMvc; private final String buyTheMilk Buy the milk ; private final String cleanupTheRoom Clean up the room ; private final String readTheBook Read the book ; BeforeEach void beforeEach(ChromeDriver driver) { this .todoMvc null ; this .todoMvc.navigateTo(); } Test DisplayName ( Creates Todo with given name ) void createsTodo() { todoMvc.createTodo(buyTheMilk); assertAll( () - assertEquals( 1 , todoMvc.getTodosLeft()), () - assertTrue(todoMvc.todoExists(buyTheMilk)) ); } Test DisplayName ( Creates Todos all with the same name DisplayName Creates Todos all with the same name ) void createsTodosWithSameName() { todoMvc.createTodos(buyTheMilk, buyTheMilk, buyTheMilk); assertEquals( 3 , todoMvc.getTodosLeft()); todoMvc.showActive(); assertEquals( 3 , todoMvc.getTodoCount()); } Test DisplayName ( Edits inline double-clicked Todo ) void editsTodo() { todoMvc.createTodos(buyTheMilk, cleanupTheRoom); todoMvc.renameTodo(buyTheMilk, readTheBook); assertAll( () - assertFalse(todoMvc.todoExists(buyTheMilk)), () - assertTrue(todoMvc.todoExists(readTheBook)), () - assertTrue(todoMvc.todoExists(cleanupTheRoom)) ); } Test DisplayName ( Removes selected Todo ) void removesTodo() { todoMvc.createTodos(buyTheMilk, cleanupTheRoom, readTheBook); todoMvc.removeTodo(buyTheMilk); assertAll( () - assertFalse(todoMvc.todoExists(buyTheMilk)), () - assertTrue(todoMvc.todoExists(cleanupTheRoom)), () - assertTrue(todoMvc.todoExists(readTheBook)) ); } Test DisplayName ( Toggles selected Todo as completed ) void togglesTodoCompleted() { todoMvc.createTodos(buyTheMilk, cleanupTheRoom, readTheBook); todoMvc.completeTodo(buyTheMilk); assertEquals( 2 , todoMvc.getTodosLeft()); todoMvc.showCompleted(); assertEquals( 1 , todoMvc.getTodoCount()); todoMvc.showActive(); assertEquals( 2 , todoMvc.getTodoCount()); } Test DisplayName ( Toggles all Todos as completed DisplayName Toggles all Todos as completed ) void togglesAllTodosCompleted() { todoMvc.createTodos(buyTheMilk, cleanupTheRoom, readTheBook); todoMvc.completeAllTodos(); assertEquals( 0 , todoMvc.getTodosLeft()); todoMvc.showCompleted(); assertEquals( 3 , todoMvc.getTodoCount()); todoMvc.showActive(); assertEquals( 0 , todoMvc.getTodoCount()); } Test DisplayName ( Clears all completed Todos DisplayName Clears all completed Todos ) void clearsCompletedTodos() { todoMvc.createTodos(buyTheMilk, cleanupTheRoom); todoMvc.completeAllTodos(); todoMvc.createTodo(readTheBook); todoMvc.clearCompleted(); assertEquals( 1 , todoMvc.getTodosLeft()); todoMvc.showCompleted(); assertEquals( 0 , todoMvc.getTodoCount()); todoMvc.showActive(); assertEquals( 1 , todoMvc.getTodoCount()); } } 更多如果您不熟悉JUnit 5则可以在我的博客上阅读此介绍 https : //blog.codeleak.pl/2017/10/junit-5-basics.html 。 本文还有一个用波兰语写的较新版本 https : //blog.qalabs.pl/junit/junit5-pierwsze-kroki/ 。 在上面的测试类中我们看到在每次测试之前ChromeDriver均已初始化并通过Selenium Jupiter扩展名因此ExtendWith(SeleniumExtension.class) 注入到设置方法 BeforeEach 中。 驱动程序对象将用于初始化页面对象。 页面对象建模技术不同并且很大程度上取决于您正在处理的项目的特征。 您可能要使用接口但这不是必需的。 您可能需要考虑在较低的抽象级别上进行建模在该级别上API公开了更详细的方法例如setTodoInput(String value) clickSubmitButton() 。 使用Selenium内置的PageFactory实现Page Object Pattern 到现在为止我们已经有一个接口可以对TodoMVC页面的行为进行建模并且我们有使用API的失败测试。 下一步是实际实现页面对象。 为此我们将使用Selenium内置的PageFactory类及其实用程序。 PageFactory类简化了Page Object模式的实现。 该类提供了一种机制用于初始化任何声明使用FindBy批注注释的WebElement或ListWebElement字段的Page Object。 可以在org.openqa.selenium.support包中找到PageFactory和支持页面对象模式实现的所有其他注释。 下面的TodoMvcPage类实现了我们之前创建的接口。 它声明了几个用FindBy注释注释的字段。 它还声明一个构造函数该构造函数采用工厂使用的WebDriver参数来初始化字段 public class TodoMvcPage implements TodoMvc { private final WebDriver driver; private static final By byTodoEdit By.cssSelector( input.edit ); private static final By byTodoRemove By.cssSelector( button.destroy ); private static final By byTodoComplete By.cssSelector( input.toggle ); FindBy (className new-todo ) private WebElement newTodoInput; FindBy (css .todo-count strong ) private WebElement todoCount; FindBy (css .todo-list li ) private ListWebElement todos; FindBy (className toggle-all ) private WebElement toggleAll; FindBy (css a[href#/active] ) private WebElement showActive; FindBy (css a[href#/completed] ) private WebElement showCompleted; FindBy (className clear-completed ) private WebElement clearCompleted; public TodoMvcPage(WebDriver driver) { this .driver driver; } Override public void navigateTo() { driver.get( http://todomvc.com/examples/vanillajs ); } public void createTodo(String todoName) { newTodoInput.sendKeys(todoName Keys.ENTER); } public void createTodos(String... todoNames) { for (String todoName : todoNames) { createTodo(todoName); } } public int getTodosLeft() { return Integer.parseInt(todoCount.getText()); } public boolean todoExists(String todoName) { return getTodos().stream().anyMatch(todoName::equals); } public int getTodoCount() { return todos.size(); } public ListString getTodos() { return todos .stream() .map(WebElement::getText) .collect(Collectors.toList()); } public void renameTodo(String todoName, String newTodoName) { WebElement todoToEdit getTodoElementByName(todoName); doubleClick(todoToEdit); WebElement todoEditInput find(byTodoEdit, todoToEdit); executeScript( arguments[0].value , todoEditInput); todoEditInput.sendKeys(newTodoName Keys.ENTER); } public void removeTodo(String todoName) { WebElement todoToRemove getTodoElementByName(todoName); moveToElement(todoToRemove); click(byTodoRemove, todoToRemove); } public void completeTodo(String todoName) { WebElement todoToComplete getTodoElementByName(todoName); click(byTodoComplete, todoToComplete); } public void completeAllTodos() { toggleAll.click(); } public void showActive() { showActive.click(); } public void showCompleted() { showCompleted.click(); } public void clearCompleted() { clearCompleted.click(); } private WebElement getTodoElementByName(String todoName) { return todos .stream() .filter(el - todoName.equals(el.getText())) .findFirst() .orElseThrow(() - new RuntimeException( Todo with name todoName not found! Todo with name not found! )); } private WebElement find(By by, SearchContext searchContext) { return searchContext.findElement(by); } private void click(By by, SearchContext searchContext) { WebElement element searchContext.findElement(by); element.click(); } private void moveToElement(WebElement element) { new Actions(driver).moveToElement(element).perform(); } private void doubleClick(WebElement element) { new Actions(driver).doubleClick(element).perform(); } private void executeScript(String script, Object... arguments) { ((JavascriptExecutor) driver).executeScript(script, arguments); } } FindBy不是唯一用于在Page Object中查找元素的注释。 还有FindBys和FindAll 。 FindBys FindBys批注用于标记Page Object上的字段以指示查找应使用一系列FindBy标记。 在此示例中Selenium将在 id menu的元素内搜索class button的元素 FindBys ({ FindBy (id menu ), FindBy (className button ) }) private WebElement element; FindAll FindAll批注用于标记Page Object上的字段以指示查找应使用一系列FindBy标记。 在此示例中Selenium将搜索所有class button的元素以及所有id menu的元素。 不保证元素按文档顺序排列 FindAll ({ FindBy (id menu ), FindBy (className button ) }) private ListWebElement webElements; PageFactory提供了几种静态方法来初始化Page Objects。 在我们的测试中在beforeEach()方法中我们需要初始化TodoMvcPage对象 BeforeEach void beforeEach(ChromeDriver driver) { this .todoMvc PageFactory.initElements(driver, TodoMvcPage. class ); this .todoMvc.navigateTo(); } PageFactory使用反射初始化对象然后初始化所有标有FindBy批注的WebElement或ListWebElement字段 FindBy不进行任何查找而是对字段进行代理。 使用此方法要求Page Object具有接受WebDriver对象的单个参数构造函数。 定位元素 那么元素何时定位 每次访问该字段都会进行查找。 因此例如当我们执行代码时 newTodoInput.sendKeys(todoName Keys.ENTER); 在createTodo()方法中实际执行的指令是 driver.findElement(By.className(new-todo)).sendKeys(todoName Keys.ENTER) 。 我们可以预料不是在对象初始化期间而是在第一个元素查找期间引发未找到元素的潜在异常。 Selenium使用代理模式来实现所描述的行为。 CacheLookup 在某些情况下每次访问带注释的字段时都不需要查找元素。 在这种情况下我们可以使用CacheLookup批注。 在我们的示例中输入字段在页面上没有更改因此可以缓存其查找 FindBy (className new-todo ) CacheLookup private WebElement newTodoInput; 运行测试 现在是执行测试的时候了。 可以从IDE或使用终端来完成 ./gradlew clean test --tests *TodoMvcTests 通过所有测试构建成功 Task :test pl.codeleak.demos.selenium.todomvc.TodoMvcTests editsTodo() PASSED pl.codeleak.demos.selenium.todomvc.TodoMvcTests togglesTodoCompleted() PASSED pl.codeleak.demos.selenium.todomvc.TodoMvcTests createsTodo() PASSED pl.codeleak.demos.selenium.todomvc.TodoMvcTests removesTodo() PASSED pl.codeleak.demos.selenium.todomvc.TodoMvcTests togglesAllTodosCompleted() PASSED pl.codeleak.demos.selenium.todomvc.TodoMvcTests createsTodosWithSameName() PASSED pl.codeleak.demos.selenium.todomvc.TodoMvcTests clearsCompletedTodos() PASSED BUILD SUCCESSFUL in 27s 3 actionable tasks: 3 executed 下一步 在本教程的下一部分中您将学习如何改善项目配置。 您将学习并行执行测试测试执行顺序参数化测试AssertJ等。 翻译自: https://www.javacodegeeks.com/2019/10/using-pagefactory-implement-page-object-pattern.html