介绍
Selenium是最广泛的web端UI自动化框架,支持java、python、ruby等编辑语言。 官网地址:https://selenium.dev/
Selenium家族
- Selenium IDE: 是浏览器的扩展插件,通过Selenium IDE我们可以录制和回放浏览器操作。
- Selenium WebDriver: Selenium的核心,提供了各种语言环境的API来支持更多控制权和编写符合标准软件开发实践的应用程序。
- Selenium Grid: 分布式测试,通过Selenium Grid可以将自动化测试脚本分发到不同的测试机器中执行。
Selenium WebDriver
一、引入Maven依赖
,
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java --><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>3.141.59</version></dependency>
仓库地址:https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java
下载浏览器驱动(版本须于浏览器一致)
- 在chrome浏览器的地址栏上面输入chrome://version获取chrome版本/在chrome设置中查看对应版本
二、下载对应的chromedriver驱动:
- 谷歌版本122驱动百度云盘获取 链接:https://pan.baidu.com/s/1VfCzRFFcJh4sGQhVUOWZEg 提取码:1234
- 其他版本驱动:https://chromedriver.storage.googleapis.com/index.html 将驱动解压至项目目录下
//引用driver路径(路径为相对路径)System.setProperty("webdriver.chrome.driver","src/test/resources/chromedriver-win32/chromedriver.exe");//引用浏览器driverChromeDriver chromeDriver =newChromeDriver();//访问URL
chromeDriver.get("https://www.qimao.com/");
基础元素定位
id定位:
By.id("id");
name定位
By.name("名称");
标签名定位
By.tagName("标签名");
样式名定位
By.className("样式名");
超链接完整文本定位
By.linkText("超链接完整文本地址");
超链接部分文本定位
By.partialLinkText("超链接部分文本地址");
css选择器定位
By.cssSelector("标签名")//实现方式可百度
xpath定位
- xpath其实就是一个path(路径),一个描述页面元素位置信息的路径,相当于元素的坐标
绝对定位(禁止使用,后期维护成本极差)
chromeDriver.findElement(By.xpath("/html/body/div[1]/div/div/header/div[2]/div/div/div[2]/div[2]/div/a/span");
相对定位 相对路径以//表示
//通过文本定位
chromeDriver.findElement(By.xpath("//span[text()=\"立即登录\"]"));
//xxx为属性名, yyy为对应的值
chromeDriver.findElement(By.xpath("//span[@xxx=\"yyy\"]"));
//模糊匹配
chromeDriver.findElement(By.xpath("//span[contains(text(),\"立即\")]"));
xpath轴定位
ancestor选取当前结点的所有先辈(父、祖父等)ancestor-or-self选取当前节点的所有先辈(父、祖父等)以及当前节点本身attribute选取当前节点的所有属性。@id等价于attribute::idchild选取当前节点的所有子元素,title等价于child:titledescendant选取当前节点的所有后代元素(子、孙等)descendant-or-self选取当前节点的所有后代运算(子、孙等)以及当前节点本身following选取文档中当前节点的结束标签之后的所有结点namespace选取当前节点的所有命名空间节点parent选取当前节点的父节点preceding选取当前节点的父节点preceding-sibling选取当前节点之前的所有同级节点self选取当前节点。等驾驭self::node()以上方式都无法定位到元素的情况下,可以考虑轴定位
By.ByXPath("//div[@class=\"qm-header-con\"]//following-sibling::span");
其他方法参考: https://blog.csdn.net/yiqiushi4748/article/details/104037528
三大等待
- 硬性等待:强制等待x秒
//缺点:有点浪费时间Thread.sleep(8);
- 隐式等待:在一定时间内只要找到元素就会结束等待,若没找到则会一直等待
//使用场景比较局限(不能判断元素是否可以点击/可见)
chromeDriver.manage().timeouts().implicitlyWait(8000,TimeUnit.MINUTES);
- 显示等待:在一定时间内只要找到元素就会结束等待,若未找到元素则会抛出超时等待异常
//实用场景很多如(可见、存在、可点击等),比较推荐WebDriverWait webDriverWait =newWebDriverWait(chromeDriver,2);
webDriverWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//span[contains(text(),\"立即\")]"))).click();
其他方法参考:https://blog.csdn.net/qq_39704682/article/details/85596644
三大切换
- 切换Iframe
//xxx为frame中的name/id属性
chromeDriver.switchTo().frame("xxx");//通过xpath进行定位
chromeDriver.switchTo().frame(chromeDriver.findElement(By.xpath("xxx")))//返回父级Iframe
driver.switchTo().parentFrame();//返回默认Iframe
driver.switchTo().defaultContent();
- 切换Alert
//获取文本
chromeDriver.switchTo().alert().getText();//点击确认按钮
……alert.accept();//取消
……alert.dismiss();
- 切换Window
newWebDriverWait(driver,8).until(ExpectedConditions.elementToBeClickable(driver.findElement(By.xpath("//a[@aria-label=\"秒杀\"]")))).click();//遍历所有窗口for(String i : driver.getWindowHandles()){
driver.switchTo().window(i);//切换窗口System.out.println("--------------"+ driver.getTitle());//获取title文本if("京东秒杀-正品保证、天天低价、限时限量".equals(driver.getTitle())){System.out.println("进来了:"+ driver.getTitle());}
鼠标操作
clickAndHold在特定元素上单击鼠标左键(不释放)release在特定元素上释放鼠标左键doubleClick在特定元素上双击鼠标左键moveToElement移动鼠标指针到特定元素contextClick在特定元素上右键单击dragAndDrop拖拽元素perform调用perform后才会真正执行操作
Actions actions=newActions(driver);WebElement webElement = driver.findElement(By.xpath("//a[text()=\"我的京东\"]"));//移动到指定位置
actions.moveToElement(webElement).build().perform();}
其他操作:https://zhuanlan.zhihu.com/p/396773865
文件上传
- 标签中带有input标签,可以通过senkeys进行上传文件
- 上传文件标签中没有input标签,则需要借助第三方工具如(autoit)官方地址:https://www.autoitscript.com/site/autoit/downloads/ 参考:https://www.cnblogs.com/yunman/p/7112882.html#:~:text=selenium%2Bjava%E5%88%A9%E7%94%A8AutoIT%E5%AE%9E%E7%8E%B0%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%201%20AutoIT%E8%84%9A%E6%9C%AC%E7%BC%96%E8%AF%91%E6%88%90%E5%8F%AF%E6%89%A7%E8%A1%8C%E6%96%87%E4%BB%B6%E5%90%8E%EF%BC%8C%E6%94%BE%E5%88%B0%E6%9C%AC%E5%9C%B0%E7%9A%84%E6%9F%90%E4%B8%80%E4%B8%AA%E7%9B%AE%E5%BD%95%E4%B8%8B,2%20%E8%87%AA%E5%8A%A8%E5%8C%96%E5%AE%9E%E7%8E%B0%E8%BF%87%E7%A8%8B%E4%B8%AD%EF%BC%8C%E9%9C%80%E8%A6%81%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87%E6%97%B6%EF%BC%8C%E9%A6%96%E5%85%88%E5%AE%9A%E4%BD%8D%E5%88%B0%E3%80%90%E4%B8%8A%E4%BC%A0%E3%80%91%E5%AD%97%E6%A0%B7%E6%96%87%E6%9C%AC%EF%BC%8C%E7%82%B9%E5%87%BB%E6%AD%A4%E6%8C%89%E9%92%AE%203%20%E6%89%A7%E8%A1%8C%E7%BC%96%E8%BE%91%E5%90%8E%E7%9A%84%E5%8F%AF%E6%89%A7%E8%A1%8C%E6%96%87%E4%BB%B6%EF%BC%8C%E5%AE%9E%E7%8E%B0%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0
验证码处理
- 测试环境去除验证码
- 找开发添加一个万能验证码绕过校验
- 添加cookie绕过:
//1.代码中添加cookieCookie cookie =newCookie("cookie名称","cookie值");
driver.manage().addCookie(cookie);//2.手动添加,在浏览器中登录账号,勾选自动登录,下次再次登录就可以不需要验证码
- JavaScript操作网页元素
document.getElementById(id);
document.getElementsByClassName(className);//点击
document.getElementById(XX).click();//修改属性
document.getElementById(XX).setAttribute('属性名','属性值');//滚动到页面最底部(通用的)
window.scrollTo(0, document.body.scrollHeight);//滚动到指定元素上去XXX.scrollIntoViewIfNeeded(true);//XXX为定位到的元素
selenium操作javascript
WebElement kw = chromeDriver.findElement(By.id("kw"));JavascriptExecutor chromeDriver1 = chromeDriver;//arguments[0]… + selenium元素定位实现输入值
chromeDriver1.executeScript("arguments[0].value=\"111441\"\n",kw);//js中实现输入值
chromeDriver1.executeScript("document.getElementById(\"kw\").value=\"111441\"\n");//
其他方法:https://zhuanlan.zhihu.com/p/403194552
数据驱动
测试中经常会使用相同的测试脚本使用不同的测试数据来执行,测试数据和测试行为完全分离, 这样的测试脚本设计模式称为数据驱动
@Test(dataProvider="userPra")publicvoiduserLogin(String userName,String password,String msg)throwsInterruptedException{System.setProperty("webdriver.chrome.driver","src/test/resources/chromedriver-win32/chromedriver.exe");ChromeDriver chromeDriver =newChromeDriver();
chromeDriver.get("https://www.baidu.com/");
chromeDriver.findElement(By.id("s-top-loginbtn")).click();WebDriverWait webDriverWait =newWebDriverWait(chromeDriver,8);
webDriverWait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//input[@placeholder=\"手机号/用户名/邮箱\"]"))).sendKeys(userName);
webDriverWait.until(ExpectedConditions.presenceOfElementLocated(By.id("TANGRAM__PSP_11__password"))).sendKeys(password);
webDriverWait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//p[@id=\"TANGRAM__PSP_11__submitWrapper\"]//label"))).click();
webDriverWait.until(ExpectedConditions.presenceOfElementLocated(By.id("TANGRAM__PSP_11__submit"))).click();String text = chromeDriver.findElement(By.id("TANGRAM__PSP_11__error")).getText();Assert.assertEquals(msg, text);}@DataProviderpublicObject[][]userPra(){Object[][] datas ={{" ","dededw","请您输入手机号/用户名/邮箱"},{"rferfer"," ","请您输入密码"},{" ","","请您输入手机号/用户名/邮箱"},{"feewf","fewfewgt","账号或密码错误,请重新输入或者"},};return datas;}
测试日志
//引入log4j依赖<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency>
//配置文件
#根logger主要定义log4j支持的日志级别及输出目的地
log4j.rootLogger =INFO,console,file
###输出信息到控制台配置###
#表示输出到控制台
log4j.appender.console =org.apache.log4j.ConsoleAppender
#将System.out作为输出
log4j.appender.console.Target=System.out
#使用灵活的布局展示日志信息
log4j.appender.console.layout =org.apache.log4j.PatternLayout
#日志详细输出信息样式
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}%-5p %c{1}:%L-%m%n
###输出信息到文件中配置###
#每天产生一个日志文件
log4j.appender.file =org.apache.log4j.DailyRollingFileAppender
#输出文件目的地
log4j.appender.file.File= log/test.log
#新的日志信息是否追加到旧的日志文件末尾
log4j.appender.file.Append=false
#使用灵活的布局展示日志信息
log4j.appender.file.layout =org.apache.log4j.PatternLayout
#日志详细输出信息样式
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}%-5p %c{1}:%L-%m%n
//需要日志的类下加privatestaticLogger logger =Logger.getLogger(LogTest.class);publicstaticvoidmain(String[] args){
logger.debug("debug级别的日志");
logger.info("info级别的日志");
logger.warn("warn级别的日志");
logger.error("error级别的日志");}
allure
官方地址:https://allurereport.org/docs/
//引入依赖<dependency><groupId>io.qameta.allure</groupId><artifactId>allure-testng</artifactId><version>2.12.1</version><scope>test</scope></dependency>//设置编码格式<properties><aspectj.version>1.8.10</aspectj.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><maven.compiler.encoding>UTF-8</maven.compiler.encoding></properties>//引入插件<build><plugins><plugin><!-- maven-surefire-plugin 配合testng执行测试用例的maven插件 --><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.22.1</version><configuration><!-- 测试失败后,是否忽略并继续测试 --><testFailureIgnore>true</testFailureIgnore><suiteXmlFiles><!-- testng配置文件名称 --><suiteXmlFile>testng.xml</suiteXmlFile></suiteXmlFiles><!--设置参数命令行 --><argLine><!--UTF-8编码 -->-Dfile.encoding=UTF-8<!-- 配置拦截器 -->-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"</argLine><systemProperties><property><!-- 配置 allure 结果存储路径 --><name>allure.results.directory</name><value>${project.build.directory}/allure-results</value></property></systemProperties></configuration><dependencies><!-- aspectjweaver maven坐标 --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>${aspectj.version}</version></dependency></dependencies></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>8</source><target>8</target></configuration></plugin></plugins></build>
将项目打包
下载allure包并配置环境遍历,然后执行 allure serve 就进入到了allure报告界面
参考:https://blog.csdn.net/qq_36396763/article/details/128816918?ops_request_misc=&request_id=&biz_id=102&utm_term=maven%E5%A6%82%E4%BD%95%E8%BF%9B%E5%85%A5allureweb%E7%95%8C%E9%9D%A2&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-3-128816918.nonecase&spm=1018.2226.3001.4187
失败用例截图截图
//将截图保存到本地publicvoidscreenshot(RemoteWebDriver chromeDriver){Date data =newDate();String format =newSimpleDateFormat("YYYY-MM-dd-HH-mm-ss").format(data);System.out.println("format:---"+format);File screenshotAs =((TakesScreenshot) chromeDriver).getScreenshotAs(OutputType.FILE);File file =null;try{
file =newFile(newFile("").getCanonicalPath()+"\\picture\\"+ format +".png");System.out.println(file);}catch(IOException e){thrownewRuntimeException(e);}try{System.out.println("file:-----"+file);FileUtils.copyFile(screenshotAs,file);}catch(Exception e){
e.printStackTrace();}}//使用监听器进行截图publicclassIHookableDemoimplementsIHookable{@Overridepublicvoidrun(IHookCallBack iHookCallBack,ITestResult iTestResult){
iHookCallBack.runTestMethod(iTestResult);if(iTestResult.getThrowable()!=null){System.out.println("222222");
allureText instance =(allureText) iTestResult.getInstance();newallureText().screenshot(instance.chromeDriver);}}}//将截图上传至allure@Attachment(value="screenshot:",type="image/jpg")publicbyte[]screen(RemoteWebDriver chromeDriver){return((TakesScreenshot)chromeDriver).getScreenshotAs(OutputType.BYTES);
版权归原作者 とぼけ 所有, 如有侵权,请联系我们删除。