毕设代做网站招聘,wordpress后台用户名和密码,PPT做音乐网站介绍,贸易公司erp管理软件总览 我已经使用了一段时间#xff0c;遇到了一些似乎可以使生活更轻松的事情。 我以为可以将其作为教程分享#xff0c;所以我将向您介绍这些部分#xff1a; 使用Maven设置Web项目#xff0c;配置Selenium以在CI上作为集成测试运行 寻找使用“页面对象”为网站中的页面… 总览 我已经使用了一段时间遇到了一些似乎可以使生活更轻松的事情。 我以为可以将其作为教程分享所以我将向您介绍这些部分 使用Maven设置Web项目配置Selenium以在CI上作为集成测试运行 寻找使用“页面对象”为网站中的页面建模的好方法以及其他创建受保护的变量的方法。 使用JPA和Hibernate对数据库执行CRUD操作并让Maven对它们执行集成测试而无需进行有时会涉及的任何昂贵且通常没有文档的设置。 这篇文章假定您对JavaSpringMaven 2和HTML感到满意。 您还需要在计算机上安装Firefox。 本教程旨在以其他方式与技术无关。 创建一个Webapp 首先我们需要一个webapp进行测试。 使用maven-webapp-archetype创建一个项目并将其称为“ selenuim-tutorial”。 要运行集成测试IT我们将使用Cargo插件。 这将启动和停止Jetty和Tomcat之类的容器。 您可以使用Cargo在一个命令中使用Jetty默认设置启动网站而无需进行任何更改 mvn cargo:run 并在浏览器中检查它 http// localhost8080 / selenuim-tutorial 您将获得一个没有欢迎文件设置的404因此将其添加到web.xml文件中 welcome-file-listwelcome-file/index.jsp/welcome-file
/welcome-file-list 如果您运行货物再次运行您现在将看到“ Hello World” 由Maven创建的页面。 配置货物 我们可以将Cargo设置为在运行测试之前启动Jetty容器然后再将其停止。 这将使我们能够启动站点运行集成测试然后再将其停止。 plugingroupIdorg.codehaus.cargo/groupIdartifactIdcargo-maven2-plugin/artifactIdversion1.2.0/versionexecutionsexecutionidstart/idphasepre-integration-test/phasegoalsgoalstart/goal/goals/executionexecutionidstop/idphasepost-integration-test/phasegoalsgoalstop/goal/goals/execution/executions
/plugin 您可以使用以下方法测试这项工作 mvn verify 此时要注意的一件事是Cargo运行在端口8080上。如果您已经有一个进程在该端口上进行侦听则可能会看到类似以下错误 java.net.BindException: Address already in use 这可能是因为您已经在该端口上运行了另一个容器。 如果要在CI上运行它它本身可以在端口8080上运行则可能需要更改。 将这些行添加到插件设置中 configurationtypestandalone/typeconfigurationpropertiescargo.servlet.port10001/cargo.servlet.port/properties/configuration
/configuration 现在该应用程序将在这里 http// localhost10001 / selenuim-tutorial / 设置集成测试阶段 接下来我们需要能够运行集成测试。 这需要Maven故障安全插件并将适当的目标添加到pom中 plugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-failsafe-plugin/artifactIdversion2.12/versionexecutionsexecutioniddefault/idgoalsgoalintegration-test/goalgoalverify/goal/goals/execution/executions
/plugin 默认情况下Failsafe期望测试匹配模式“ src / test / java / * / * IT.java”。 让我们创建一个测试来证明这一点。 请注意我尚未从Junit 3.8.1更改过。 我稍后会解释原因。 这是一个基本的不完整的测试 package tutorial;import junit.framework.TestCase;public class IndexPageIT extends TestCase {Overrideprotected void setUp() throws Exception {super.setUp();}Overrideprotected void tearDown() throws Exception {super.tearDown();}public void testWeSeeHelloWorld() {fail();}
} 测试有效 mvn verify 您应该看到一个测试失败。 要使用Selenium进行测试您需要向pom.xml添加测试范围的依赖项 dependencygroupIdorg.seleniumhq.selenium/groupIdartifactIdselenium-firefox-driver/artifactIdversion2.19.0/versionscopetest/scope
/dependency 现在我们可以对测试进行一些更改 import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;…private URI siteBase;private WebDriver drv;Overrideprotected void setUp() throws Exception {super.setUp();siteBase new URI(http://localhost:10001/selenuim-tutorial/);drv new FirefoxDriver();}...public void testWeSeeHelloWorld() {drv.get(siteBase.toString());assertTrue(drv.getPageSource().contains(Hello World));} 稍后我们将删除这些硬编码值。 再次运行 mvn verify 您应该不会看到任何故障。 您将拥有一个挥之不去的Firefox。 它不会关闭。 运行此测试100次您将运行100个Firefox。 这将很快成为一个问题。 我们可以通过在测试中添加以下初始化块来解决此问题 {Runtime.getRuntime().addShutdownHook(new Thread() {Overridepublic void run() {drv.close();}});} 自然如果我们创建另一个测试我们将很快违反DRY原则。 我们将在下一部分中讨论该问题并查看需要数据库连接时发生的情况以及其他一些方法来确保您的测试易于编写和维护。 Spring语境 在前面的示例中应用程序的URI和使用的驱动程序都经过了硬编码。 假设您熟悉Spring上下文那么更改这些上下文就很简单了。 首先我们将添加正确的依赖项 dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion3.1.1.RELEASE/versionscopetest/scope
/dependency 这将使我们能够使用和应用程序上下文注入依赖项。 但是我们还需要正确的Junit运行程序来测试它可以在spring-test软件包中找到它 dependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion3.1.1.RELEASE/versionscopetest/scope
/dependency 现在我们可以更新测试以使用它。 首先我们需要创建src / test / resources / applicationContext-test.xml ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsdbean idsiteBase classjava.net.URIconstructor-arg valuehttp://localhost:10001/selenuim-tutorial/ //beanbean iddrv classorg.openqa.selenium.firefox.FirefoxDriver destroy-methodquit/
/beans Spring完成后将清除浏览器因此我们可以从AbstractIT中删除关闭钩子。 这比让测试用例执行此操作更健壮。 弹簧测试不适用于JUnit 3它至少需要JUnit 4.5。 让我们在pom.xml中更新到版本4.10 dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.10/versionscopetest/scope
/dependency 最后我们需要更新测试以同时使用Spring和JUnit 4.x package tutorial;import static org.junit.Assert.assertTrue;import java.net.URI;import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration(locations { /applicationContext-test.xml })
public class IndexPageIT {Autowiredprivate URI siteBase;Autowiredprivate WebDriver drv;Testpublic void testWeSeeHelloWorld() {
... 这些更改将配置从硬编码值转移到XML配置。 现在我们可以将要测试的位置更改为例如其他主机并更改我们正在使用的Web驱动程序这留给用户练习。 关于浏览器的快速说明。 我发现浏览器更新后测试通常会开始失败。 似乎有两种解决方案 升级到最新版本的Web驱动程序。 不要升级浏览器。 我出于安全原因怀疑在大多数情况下第一种选择是最好的 抽象IT 当前您需要复制IoC的所有代码。 一个简单的重构可以解决这个问题。 我们将为所有测试和上拉通用功能创建一个超类。 出于重构的目的继承使用的是继承而不是合成。 package tutorial;import java.net.URI;import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration(locations { /applicationContext-test.xml })
public abstract class AbstractIT {Autowiredprivate URI siteBase;Autowiredprivate WebDriver drv;public URI getSiteBase() {return siteBase;}public WebDriver getDrv() {return drv;}
}package tutorial;import static org.junit.Assert.assertTrue;import org.junit.Test;public class IndexPageIT extends AbstractIT {Testpublic void testWeSeeHelloWorld() {getDrv().get(getSiteBase().toString());assertTrue(getDrv().getPageSource().contains(Hello World));}
} 页面对象 “页面对象”是封装页面的单个实例并为该实例提供程序化API的对象。 基本页面可能是 package tutorial;import java.net.URI;import org.openqa.selenium.WebDriver;public class IndexPage {/*** param drv* A web driver.* param siteBase* The root URI of a the expected site.* return Whether or not the driver is at the index page of the site.*/public static boolean isAtIndexPage(WebDriver drv, URI siteBase) {return drv.getCurrentUrl().equals(siteBase);}private final WebDriver drv;private final URI siteBase;public IndexPage(WebDriver drv, URI siteBase) {if (!isAtIndexPage(drv, siteBase)) { throw new IllegalStateException(); }this.drv drv;this.siteBase siteBase;}
} 请注意我已经提供了一个静态方法来返回我们是否在索引页上并且已经对其进行了注释对于这种自填充方法这是不必要的。 页面对象形成一个API值得记录。 您还将看到如果URL不正确我们将引发异常。 值得考虑使用什么条件来识别页面。 任何可能更改的内容例如页面标题可能会在不同语言之间更改都是一个糟糕的选择。 不变的东西和机器可读的东西例如页面的路径是不错的选择。 如果要更改路径则需要更改测试。 现在让我们自己制造一个问题。 我想将其添加到index.jsp但是生成HTML无法解析 % throw new RuntimeException(); % 相反我们将创建一个新的servlet但是首先我们需要将servlet-api添加到pom.xml中 dependencygroupIdjavax.servlet/groupIdartifactIdservlet-api/artifactIdversion2.5/versionscopeprovided/scope
/dependencypackage tutorial;import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class IndexServlet extends HttpServlet {private static final long serialVersionUID 1L;protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {throw new RuntimeException();}
} 将其添加到web.xml并删除现在不必要的欢迎页面 !DOCTYPE web-app PUBLIC-//Sun Microsystems, Inc.//DTD Web Application 2.3//ENhttp://java.sun.com/dtd/web-app_2_3.dtd
web-appservletservlet-nameIndexServlet/servlet-nameservlet-classtutorial.IndexServlet/servlet-class/servletservlet-mappingservlet-nameIndexServlet/servlet-nameurl-pattern//url-pattern/servlet-mapping
/web-app 更新IndexPageIT Testpublic void testWeSeeHelloWorld() {getDrv().get(getSiteBase().toString());new IndexPage(getDrv(), getSiteBase());} 再次运行测试。 它通过了。 这可能不是您想要的行为。 Selenium没有提供通过WebDriver实例检查HTTP状态代码的方法。 容器之间的默认错误页面也没有足够一致例如与在Tomcat上运行时所发生的情况进行比较 我们无法对错误页面的内容进行假设以判断是否发生错误。 我们的索引页面当前不具备任何机器可读功能因此无法从错误页面中分辨出来。 要整理请修改servlet以显示index.jsp protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {getServletContext().getRequestDispatcher(/index.jsp).forward(request, response);} 当前index.jsp有点太简单了。 在index.jsp旁边创建一个名为create-order.jsp的新页面并在index.jsp上创建指向该页面的链接。 我们可以为订单页面创建一个新类并创建一个将我们从索引页面导航到订单页面的方法。 将以下内容添加到index.jsp中 a hrefcreate-order.jspCreate an order/a create-order.jsp现在可以为空。 我们还可以为其创建一个页面对象 package tutorial;import java.net.URI;import org.openqa.selenium.WebDriver;public class CreateOrderPage {public static boolean isAtCreateOrderPage(WebDriver drv, URI siteBase) {return drv.getCurrentUrl().equals(siteBase.toString() create-order.jsp);}private final WebDriver drv;private final URI siteBase;public CreateOrderPage(WebDriver drv, URI siteBase) {if (!isAtCreateOrderPage(drv, siteBase)) { throw new IllegalStateException(); }this.drv drv;this.siteBase siteBase;}
} 将以下依赖项添加到pom.xml中这将为我们提供一些有用的注释 dependencygroupIdorg.seleniumhq.selenium/groupIdartifactIdselenium-support/artifactIdversion2.19.0/versionscopetest/scope
/dependency 我们现在可以充实IndexPage了 FindBy(css a[hrefcreate-order.jsp])private WebElement createOrderLink;public IndexPage(WebDriver drv, URI siteBase) {if (!isAtIndexPage(drv, siteBase)) { throw new IllegalStateException(); }PageFactory.initElements(drv, this);this.drv drv;this.siteBase siteBase;} 对PageFactory.initElements的此调用将填充带有FindBy注释的字段该对象具有与网页上的元素匹配的对象。 请注意使用CSS选择器是为了以不太可能更改的方式定位链接。 其他方法包括使用链接文本匹配页面上的元素可能会因不同的语言而改变。 现在我们可以在IndexPages上创建一个方法该方法导航到CreateOrderPages。 public CreateOrderPage createOrder() {createOrderLink.click();return new CreateOrderPage(drv, siteBase);} 最后我们可以在IndexPageIT中为此链接创建一个测试 Testpublic void testCreateOrder() {getDrv().get(getSiteBase().toString());new IndexPage(getDrv(), getSiteBase()).createOrder();assertTrue(CreateOrderPage.isAtCreateOrderPage(getDrv(), getSiteBase()));} 执行mvn verify您应该找到新的测试通过。 至此我们有两个测试无法在它们之间进行清理。 他们在两个测试中使用相同的WebDriver实例最后一页仍将打开并且设置的所有cookie都将保持不变。 为多个测试创建单个WebDriver实例的优缺点。 主要优点是减少了打开和关闭浏览器的时间但缺点是每次测试Cookie设置和弹出窗口打开后浏览器实际上都会变脏。 我们可以使用AbstractIT中的适当setUp方法确保每次测试之前它都是干净的 Beforepublic void setUp() {getDrv().manage().deleteAllCookies();getDrv().get(siteBase.toString());} 有其他方法可以解决我将让您自行研究在每次测试之前创建新的WebDriver实例的方法。 FindBy批注在窗体上使用时特别有用。 向create-order.jsp添加新表单 form methodpost namecreate-orderItem: input nameitem/ br/Amount: input nameamount/br/input typesubmit//form 将这些WebElement添加到CreateOrderPage中并添加一种提交表单的方法 FindBy(css form[namecreate-order] input[nameitem])private WebElement itemInput;FindBy(css form[namecreate-order] input[nameamount])private WebElement amountInput;FindBy(css form[namecreate-order] input[typesubmit])private WebElement submit;public CreateOrderPage(WebDriver drv, URI siteBase) {if (!isAtCreateOrderPage(drv, siteBase)) { throw new IllegalStateException(); }PageFactory.initElements(drv, this);this.drv drv;this.siteBase siteBase;}public CreateOrderPage submit(String item, String amount) {itemInput.sendKeys(item);amountInput.sendKeys(amount);submit.click();return new CreateOrderPage(drv, siteBase);} 最后我们可以为此创建一个测试 package tutorial;import static org.junit.Assert.*;import org.junit.Test;public class CreateOrderPageIT extends AbstractIT {Testpublic void testSubmit() {new IndexPage(getDrv(), getSiteBase()).createOrder().submit(foo, 1.0);}
} 结论 您可能要注意的一件事是submit方法不需要将金额作为您期望的数字。 您可以创建一个测试以查看提交的是字符串而不是数字。 集成测试的编写可能很耗时并且由于诸如元素ID或输入名称之类的事物的更改而容易损坏。 结果创建它们所获得的最大好处是最初仅在您站点内的业务关键路径上创建它们例如产品订购客户注册流程和付款。 在本教程的下一部分中我们将研究使用一些数据支持测试以及由此带来的挑战。 参考我们的JCG合作伙伴 Alex Collins在Alex Collins的博客上提供的教程 教程与硒的集成测试–第1部分 教程与硒的集成测试–第2部分 。 翻译自: https://www.javacodegeeks.com/2012/04/integration-testing-with-selenium.html