最近在公司搭建了一套基于maven+selenium+java+testng+jenkins的自动化测试框架,免得以后重写记录下

工程目录

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Realinsight4.0</groupId>
<artifactId>Realinsight4.0</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Realinsight4.0</name> <dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-server</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version> </dependency>
<dependency>
<groupId>org.uncommons</groupId>
<artifactId>reportng</artifactId>
<version>1.1.4</version>
<exclusions>
<exclusion>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.aventstack</groupId>
<artifactId>extentreports</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>com.relevantcodes</groupId>
<artifactId>extentreports</artifactId>
<version>2.40.2</version>
</dependency>
<dependency>
<groupId>com.vimalselvam</groupId>
<artifactId>testng-extentsreport</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
<!--
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<properties>
<property>
<name>usedefaultlisteners</name>
<value>false</value>
</property>
<property>
<name>listener</name>
<value>org.uncommons.reportng.HTMLReporter,org.uncommons.reportng.JUnitXMLReporter</value>
</property>
</properties>
<workingDirectory></workingDirectory> </configuration>
</plugin>
-->
</plugins>
</build> </project>

testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Realinsight4.0">
<listeners>
<listener class-name="utils.RetryListener" />
<listener class-name="utils.TestngListener" />
<listener class-name="utils.ExtentReporterListener" />
</listeners>
<test name="登陆测试" verbose="10" preserve-order="true">
<classes>
<class name="testcase.login.login"/>
<class name="testcase.login.loginWithParas"/>
<class name="testcase.login.createAccount"/>
<class name="testcase.login.lockAccount"/>
<class name="testcase.login.resetPwd"/>
<class name="testcase.login.logout"/>
</classes>
</test>
<test name="数据集测试" verbose="10" preserve-order="true">
<classes>
<class name="testcase.boardsheet.UploadData"/>
<class name="testcase.boardsheet.AggRegate"/>
<class name="testcase.boardsheet.AppendData"/>
<class name="testcase.boardsheet.CreatBySQL"/>
<class name="testcase.boardsheet.AppendMerge"/>
<class name="testcase.boardsheet.DimensionalityReduction"/>
<class name="testcase.boardsheet.ReplaceData"/>
</classes>
</test>
<test name="仪表板测试" verbose="10" preserve-order="true">
<classes>
<class name="testcase.dashboard.CreateDashBoard"/>
<class name="testcase.dashboard.CreateChart"/>
<class name="testcase.dashboard.ChartOperation"/>
<class name="testcase.dashboard.TextOperation"/>
</classes>
</test>
<test name="刪除数据" verbose="10" preserve-order="true">
<classes>
<class name="testcase.boardsheet.Deleteboardsheet"/>
</classes>
</test>
</suite> <!-- Suite -->

log4j.properties

log4j.rootCategory=INFO, stdout , R   

log4j.appender.CONSOLE = org.apache.log4j.ConsoleAppender\u00A0
log4j.appender.Threshold = DEBUG\u00A0
log4j.appender.CONSOLE.Target = System.out\u00A0
log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout\u00A0
log4j.appender.CONSOLE.layout.ConversionPattern = [framework] % d - % c -%- 4r [ % t] %- 5p % c % x - % m % n\u00A0 ---------------------
\u4F5C\u8005\uFF1AJXNUleo
\u6765\u6E90\uFF1ACSDN
\u539F\u6587\uFF1Ahttps://blog.csdn.net/m0_37874657/article/details/80536086
\u7248\u6743\u58F0\u660E\uFF1A\u672C\u6587\u4E3A\u535A\u4E3B\u539F\u521B\u6587\u7AE0\uFF0C\u8F6C\u8F7D\u8BF7\u9644\u4E0A\u535A\u6587\u94FE\u63A5\uFF01
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[YG] %p [%t] %C.%M(%L) | %m%n log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=${project}/WEB-INF/logs/app.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
1log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n log4j.logger.com.neusoft=DEBUG
log4j.logger.com.opensymphony.oscache=ERROR
log4j.logger.net.sf.navigator=ERROR
log4j.logger.org.apache.commons=ERROR
log4j.logger.org.apache.struts=WARN
log4j.logger.org.displaytag=ERROR
log4j.logger.org.springframework=DEBUG
log4j.logger.com.ibatis.db=WARN
log4j.logger.org.apache.velocity=FATAL log4j.logger.com.canoo.webtest=WARN log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
log4j.logger.org.hibernate=DEBUG
log4j.logger.org.logicalcobwebs=WARN log4j.rootCategory=INFO, stdout , R log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=D:\\logs\\YG.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
1log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n log4j.logger.com.neusoft=DEBUG
log4j.logger.com.opensymphony.oscache=ERROR
log4j.logger.net.sf.navigator=ERROR
log4j.logger.org.apache.commons=ERROR
log4j.logger.org.apache.struts=WARN
log4j.logger.org.displaytag=ERROR
log4j.logger.org.springframework=DEBUG
log4j.logger.com.ibatis.db=WARN
log4j.logger.org.apache.velocity=FATAL log4j.logger.com.canoo.webtest=WARN log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
log4j.logger.org.hibernate=DEBUG
log4j.logger.org.logicalcobwebs=WARN

ExtentReporterListener.java

package utils;

import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.ResourceCDN;
import com.aventstack.extentreports.Status;
import com.aventstack.extentreports.model.TestAttribute;
import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
import com.aventstack.extentreports.reporter.configuration.ChartLocation;
import com.aventstack.extentreports.reporter.configuration.Theme;
import org.testng.*;
import org.testng.xml.XmlSuite; import java.io.File;
import java.util.*; public class ExtentReporterListener implements IReporter {
//生成的路径以及文件名
private static final String OUTPUT_FOLDER = "test-output/";
private static final String FILE_NAME = "index.html"; private ExtentReports extent; @Override
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
init();
boolean createSuiteNode = false;
if(suites.size()>1){
createSuiteNode=true;
}
for (ISuite suite : suites) {
Map<String, ISuiteResult> result = suite.getResults();
//如果suite里面没有任何用例,直接跳过,不在报告里生成
if(result.size()==0){
continue;
}
//统计suite下的成功、失败、跳过的总用例数
int suiteFailSize=0;
int suitePassSize=0;
int suiteSkipSize=0;
ExtentTest suiteTest=null;
//存在多个suite的情况下,在报告中将同一个一个suite的测试结果归为一类,创建一级节点。
if(createSuiteNode){
suiteTest = extent.createTest(suite.getName()).assignCategory(suite.getName());
}
boolean createSuiteResultNode = false;
if(result.size()>1){
createSuiteResultNode=true;
}
for (ISuiteResult r : result.values()) {
ExtentTest resultNode;
ITestContext context = r.getTestContext();
if(createSuiteResultNode){
//没有创建suite的情况下,将在SuiteResult的创建为一级节点,否则创建为suite的一个子节点。
if( null == suiteTest){
resultNode = extent.createTest(r.getTestContext().getName());
}else{
resultNode = suiteTest.createNode(r.getTestContext().getName());
}
}else{
resultNode = suiteTest;
}
if(resultNode != null){
resultNode.getModel().setName(suite.getName()+" : "+r.getTestContext().getName());
if(resultNode.getModel().hasCategory()){
resultNode.assignCategory(r.getTestContext().getName());
}else{
resultNode.assignCategory(suite.getName(),r.getTestContext().getName());
}
resultNode.getModel().setStartTime(r.getTestContext().getStartDate());
resultNode.getModel().setEndTime(r.getTestContext().getEndDate());
//统计SuiteResult下的数据
int passSize = r.getTestContext().getPassedTests().size();
int failSize = r.getTestContext().getFailedTests().size();
int skipSize = r.getTestContext().getSkippedTests().size();
suitePassSize += passSize;
suiteFailSize += failSize;
suiteSkipSize += skipSize;
if(failSize>0){
resultNode.getModel().setStatus(Status.FAIL);
}
resultNode.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",passSize,failSize,skipSize));
}
buildTestNodes(resultNode,context.getFailedTests(), Status.FAIL);
buildTestNodes(resultNode,context.getSkippedTests(), Status.SKIP);
buildTestNodes(resultNode,context.getPassedTests(), Status.PASS);
}
if(suiteTest!= null){
suiteTest.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",suitePassSize,suiteFailSize,suiteSkipSize));
if(suiteFailSize>0){
suiteTest.getModel().setStatus(Status.FAIL);
}
} }
// for (String s : Reporter.getOutput()) {
// extent.setTestRunnerOutput(s);
// } extent.flush();
} private void init() {
//文件夹不存在的话进行创建
File reportDir= new File(OUTPUT_FOLDER);
if(!reportDir.exists()&& !reportDir .isDirectory()){
reportDir.mkdir();
}
ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(OUTPUT_FOLDER + FILE_NAME);
// 设置静态文件的DNS
//怎么样解决cdn.rawgit.com访问不了的情况
htmlReporter.config().setEncoding("gbk");
htmlReporter.config().setResourceCDN(ResourceCDN.EXTENTREPORTS); htmlReporter.config().setDocumentTitle("自动化测试报告");
htmlReporter.config().setReportName("自动化测试报告");
htmlReporter.config().setChartVisibilityOnOpen(true);
htmlReporter.config().setTestViewChartLocation(ChartLocation.TOP);
htmlReporter.config().setTheme(Theme.STANDARD);
htmlReporter.config().setCSS(".node.level-1 ul{ display:none;} .node.level-1.active ul{display:block;}");
extent = new ExtentReports();
extent.attachReporter(htmlReporter);
extent.setReportUsesManualConfiguration(true);
} private void buildTestNodes(ExtentTest extenttest, IResultMap tests, Status status) {
//存在父节点时,获取父节点的标签
String[] categories=new String[0];
if(extenttest != null ){
List<TestAttribute> categoryList = extenttest.getModel().getCategoryContext().getAll();
categories = new String[categoryList.size()];
for(int index=0;index<categoryList.size();index++){
categories[index] = categoryList.get(index).getName();
}
} ExtentTest test; if (tests.size() > 0) {
//调整用例排序,按时间排序
Set<ITestResult> treeSet = new TreeSet<ITestResult>(new Comparator<ITestResult>() {
@Override
public int compare(ITestResult o1, ITestResult o2) {
return o1.getStartMillis()<o2.getStartMillis()?-1:1;
}
});
treeSet.addAll(tests.getAllResults());
for (ITestResult result : treeSet) {
Object[] parameters = result.getParameters();
String name="";
//如果有参数,则使用参数的toString组合代替报告中的name
for(Object param:parameters){
name+=param.toString();
}
if(name.length()>0){
if(name.length()>50){
name= name.substring(0,49)+"...";
}
}else{
name = result.getMethod().getMethodName();
}
if(extenttest==null){
test = extent.createTest(name);
}else{
//作为子节点进行创建时,设置同父节点的标签一致,便于报告检索。
test = extenttest.createNode(name).assignCategory(categories);
}
//test.getModel().setDescription(description.toString());
//test = extent.createTest(result.getMethod().getMethodName());
for (String group : result.getMethod().getGroups())
test.assignCategory(group); List<String> outputList = Reporter.getOutput(result);
for(String output:outputList){
//将用例的log输出报告中
test.debug(output);
}
if (result.getThrowable() != null) {
test.log(status, result.getThrowable());
}
else {
test.log(status, "Test " + status.toString().toLowerCase() + "ed");
} test.getModel().setStartTime(getTime(result.getStartMillis()));
test.getModel().setEndTime(getTime(result.getEndMillis()));
}
}
} private Date getTime(long millis) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(millis);
return calendar.getTime();
}
}

OverrideRetry.java

package utils;
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult; public class OverrideRetry implements IRetryAnalyzer {
private int count = 1;
private int max_count = 3; @Override
public boolean retry(ITestResult result) {
System.out.println("执行用例:"+result.getName()+",第"+count+"次失败");
if (count < max_count) {
count++;
return true;
}
return false;
}
}

ParasUtils.java

package utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties; public class ParasUtils {
private String db_url;
private String db_username;
private String db_password;
private String db_tableName;
private String url;
private String username;
private String password;
private String userData;
private String downloadDir;
private String uploadDir;
private String chromePath; public void readParas(){
try {
InputStream inStream = new FileInputStream(new File(System.getProperty("user.dir")+"\\datas\\Paras.properties"));
Properties prop = new Properties();
prop.load(inStream);
setDb_url(prop.getProperty("db_url"));
setDb_username(prop.getProperty("db_username"));
setDb_password(prop.getProperty("db_password"));
setDb_tableName(prop.getProperty("db_tableName"));
setUrl(prop.getProperty("url"));
setUsername(prop.getProperty("username"));
setPassword(prop.getProperty("password"));
setUserData(prop.getProperty("user-data-dir"));
setUploadDir(prop.getProperty("uploadDir"));
setDownloadDir(prop.getProperty("downloadDir"));
setChromePath(prop.getProperty("chromePath")); } catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public String getUrl() {
readParas();
return url;
} public void setUrl(String url) {
this.url = url;
} public String getUsername() {
readParas();
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
readParas();
return password;
} public void setPassword(String password) {
this.password = password;
} public String getUserData() {
readParas();
return userData;
} public void setUserData(String userData) {
this.userData = userData;
} public String getDownloadDir() {
readParas();
return downloadDir;
} public void setDownloadDir(String downloadDir) {
this.downloadDir = downloadDir;
} public String getDb_username() {
return db_username;
} public void setDb_username(String db_username) {
this.db_username = db_username;
} public String getDb_url() {
return db_url;
} public void setDb_url(String db_url) {
this.db_url = db_url;
} public String getDb_password() {
return db_password;
} public void setDb_password(String db_password) {
this.db_password = db_password;
} public String getDb_tableName() {
return db_tableName;
} public void setDb_tableName(String db_tableName) {
this.db_tableName = db_tableName;
} public void setUp() {
// TODO Auto-generated method stub } public String getUploadDir() {
return uploadDir;
} public void setUploadDir(String uploadDir) {
this.uploadDir = uploadDir;
} public String getChromePath() {
return chromePath;
} public void setChromePath(String chromePath) {
this.chromePath = chromePath;
} }

ReadCSV.java

package utils;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List; public class ReadCSV {
public static Object [][] readCSV(String fileName)
throws IOException {
//读取CSV文件的方法
List<Object[]> records = new ArrayList<Object[]>();
String record;
BufferedReader file = new BufferedReader(new InputStreamReader(new FileInputStream(fileName),"UTF-8"));
file.readLine();
while ((record=file.readLine())!=null){
String fields[] = record.split(",");
records.add(fields);
}
file.close(); Object[][] results = new Object[records.size()][];
for (int i=0; i<records.size();i++){
results[i] = records.get(i);
}
return results;
} }

RetryListener.java

package utils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import org.testng.IAnnotationTransformer;
import org.testng.IRetryAnalyzer;
import org.testng.annotations.ITestAnnotation; public class RetryListener implements IAnnotationTransformer { public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { IRetryAnalyzer retry = annotation.getRetryAnalyzer();
if (retry == null) {
annotation.setRetryAnalyzer(OverrideRetry.class); // 这个类名一定要和上方的对上 }
}
}

TestngListener.java

package utils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set; import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.testng.ITestContext;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter; import common.basic; public class TestngListener extends TestListenerAdapter {
private static Logger logger = Logger.getLogger(TestngListener.class); @Override
public void onTestFailure(ITestResult tr) {
super.onTestFailure(tr);
logger.info(tr.getName() + "Failure");
basic basic=(basic)tr.getInstance();
takeScreenshot(basic.driver);
} @Override
public void onTestSkipped(ITestResult tr) {
super.onTestSkipped(tr);
logger.info(tr.getName() + "Skipped");
basic basic=(basic)tr.getInstance();
takeScreenshot(basic.driver);
} @Override
public void onTestSuccess(ITestResult tr) {
super.onTestSuccess(tr);
logger.info(tr.getName() + "Success");
} @Override
public void onTestStart(ITestResult tr) {
super.onTestStart(tr);
logger.info(tr.getName() + "Start");
} @Override
public void onFinish(ITestContext testContext) {
super.onFinish(testContext);
ArrayList<ITestResult> testsToBeRemoved = new ArrayList<ITestResult>();
Set<Integer> passedTestIds = new HashSet<Integer>();
for (ITestResult passedTest : testContext.getPassedTests()
.getAllResults()) {
logger.info("PassedTests = " + passedTest.getName());
passedTestIds.add(getId(passedTest));
} Set<Integer> failedTestIds = new HashSet<Integer>();
for (ITestResult failedTest : testContext.getFailedTests()
.getAllResults()) {
logger.info("failedTest = " + failedTest.getName());
int failedTestId = getId(failedTest);
if (failedTestIds.contains(failedTestId)
|| passedTestIds.contains(failedTestId)) {
testsToBeRemoved.add(failedTest);
} else {
failedTestIds.add(failedTestId);
}
} for (Iterator<ITestResult> iterator = testContext.getFailedTests()
.getAllResults().iterator(); iterator.hasNext();) {
ITestResult testResult = iterator.next();
if (testsToBeRemoved.contains(testResult)) {
logger.info("Remove repeat Fail Test: " + testResult.getName());
iterator.remove();
}
} } private int getId(ITestResult result) {
int id = result.getTestClass().getName().hashCode();
id = id + result.getMethod().getMethodName().hashCode();
id = id
+ (result.getParameters() != null ? Arrays.hashCode(result
.getParameters()) : 0);
return id;
} private void takeScreenshot(WebDriver driver,String screenPath) {
try {
File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(screenPath));
} catch (IOException e) {
System.out.println("Screen shot error: " + screenPath);
}
} public void takeScreenshot(WebDriver driver) {
String screenName = String.valueOf(new Date().getTime()) + ".jpg";
File dir = new File("test-output/snapshot");
if (!dir.exists())
dir.mkdirs();
String screenPath = dir.getAbsolutePath() + "\\" + screenName;
this.takeScreenshot(driver,screenPath);
} }

loginPage.java

package page;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.*; public class loginPage{
//用户名
@FindBy(id = "username")
public WebElement username; //密码
@FindBy(id = "pwd")
public WebElement password; //登录按钮
@FindBy(xpath = "//button[text()='登录' and @class='btn login-btn']")
public WebElement loginButton; //个人中心
@FindBy(xpath = "//li[@class='personal-center nav-info__item']")
public WebElement personalCenter; //个人中心-名称
@FindBy(xpath = "//div[@class='personal-info fl no-border']/div[2]/p[@class='name nowrap']")
public WebElement nameInfo; //账号已休眠提示
@FindBy(xpath = "//div[text()='该账号已休眠,请联系管理员激活' and @class='jquery-notific8-message']")
public WebElement stopUserMessage; //用户名密码错误提示
@FindBy(xpath = "//div[text()='用户名密码错误' and @class='jquery-notific8-message']")
public WebElement wrongPwd; //登录错误次数过多提示
@FindBy(xpath = "//div[text()='您的用户登录错误次数过多,已被锁定,请联系管理员' and @class='jquery-notific8-message']")
public WebElement lockMessage; //解锁成功提示
@FindBy(xpath = "//div[text()='解锁成功' and @class='jquery-notific8-message']")
public WebElement unlockMessage; //重置密码成功提示
@FindBy(xpath = "//div[text()='重置密码成功' and @class='jquery-notific8-message']")
public WebElement resetMessage; //第一次登录修改密码提示
@FindBy(xpath = "//div[text()='您是第一次登录,请修改密码' and @class='jquery-notific8-message']")
public WebElement firstLoginMessage; //创建成功
@FindBy(xpath = "//div[text()='创建成功' and @class='jquery-notific8-message']")
public WebElement createSuccessMessage; //退出按鈕
@FindBy(xpath = "//div[text()='退出' and @class='logout operate-item']")
public WebElement logoutButton; //进入时间
@FindBy(xpath = "//li[@fieldname='进入时间']")
public WebElement time; //时间排序
@FindBy(xpath = "//li[@fieldname='进入时间']/div/div[2]/div/div/div[2]")
public WebElement sortArrow; //登出成功日志记录
@FindBy(xpath = "//tbody/tr[3]/td[contains(text(),'登出成功')]")
public WebElement logoutLogs; //ygtest用户
@FindBy(xpath = "td[@text='ygtest')]")
public WebElement ygtest; //ygtest01用户
@FindBy(xpath = "//tbody/tr/td[contains(text(),'ygtest01')]")
public WebElement ygtest01; //ygtest02用户
@FindBy(xpath = "//tbody/tr/td[contains(text(),'ygtest02')]")
public WebElement ygtest02; //输入关键字搜索
@FindBy(xpath = "//input[@placeholder='输入关键字搜索']")
public WebElement searchByKey; //用户菜单
@FindBy(id="userManage")
public WebElement userManage; //配置管理菜单
@FindBy(id="configManage")
public WebElement configManage; //锁定
@FindBy(xpath = "//i[@class='ygmat-status-lock'and @title='锁定']")
public WebElement lockIcon; //重置密码
@FindBy(xpath = "//i[@class='ygmat-reset cursor-pointer resetPwd-btn mr8'and @title='重置密码']")
public WebElement resetPwd; //新增用户
@FindBy(xpath = "//li[@title='新增用户']")
public WebElement addUser; //用户名
@FindBy(xpath = "//input[@validatename='用户名']")
public WebElement newusername; //显示名
@FindBy(xpath = "//input[@validatename='显示名']")
public WebElement newshowname; //原密码
@FindBy(xpath = "//input[@validatename='原密码']")
public WebElement oldPwd; //新密码
@FindBy(xpath = "//input[@validatename='新密码']")
public WebElement newPwd; //再次输入
@FindBy(xpath = "//input[@validatename='再次输入']")
public WebElement againPwd; //所属组织
@FindBy(xpath = "//div[@class='belong-org clearfix mb10']/div/button")
public WebElement belongOrg; //所属用户组
@FindBy(xpath = "//div[@class='belong-group clearfix']/div/button")
public WebElement belongGroup; //组织
@FindBy(xpath = "//li[@class='folder-item']/p/input")
public WebElement selectGroup; public loginPage(WebDriver driver){
PageFactory.initElements(driver, this);
}
}

basic.java

package common;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert; import org.apache.log4j.Logger; import page.*;
import utils.*; public class basic extends ParasUtils{
private static Logger logger=Logger.getLogger(basic.class); public ChromeDriver driver;
public WebDriverWait wait;
public loginPage loginPage;
public commonPage commonPage; //初始化浏览器
public void initBrowser(){
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\datas\\chromedriver2.37.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("UserDataDir="+this.getUserData());
options.setBinary(this.getChromePath()+"chrome.exe");
driver = new ChromeDriver(options);
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS);
logger.info("打开浏览器:"+this.getUrl());
driver.get(this.getUrl());
} //登录
public void login(){
initBrowser();
loginPage=new loginPage(driver);
loginPage.username.sendKeys(this.getUsername());
loginPage.password.sendKeys(this.getPassword());
threadwait(1000);
click(loginPage.loginButton);
logger.info("登录成功");
commonPage=new commonPage(driver);
} //管理员登录
public void login_Manager(){
initBrowser();
loginPage=new loginPage(driver);
loginPage.username.sendKeys("mat");
loginPage.password.sendKeys("1234.abcd");
threadwait(1000);
click(loginPage.loginButton);
logger.info("登录成功");
commonPage=new commonPage(driver);
} public void refreshBrower(){
driver.navigate().refresh();
} //退出
public void logout(){
driver.quit();
logger.info("退出浏览器成功");
} //等待元素可被点击
public void waitFor(WebElement element){
wait=new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.elementToBeClickable(element));
} //等待元素点击
public void click(WebElement element){
try {
waitFor(element);
logger.info("点击"+element.getTagName()+element.getText());
element.click();
} catch (Exception e) {
threadwait(2000);
element.click();
}
} //等待元素点击
public void mouseClick(WebElement element){
Actions actions=new Actions(driver);
logger.info("点击"+element.getText());
try {
actions.contextClick(element);
} catch (Exception e) {
threadwait(2000);
actions.contextClick(element);
}
} //强制等待
public void threadwait(long time){
try {
Thread.sleep(time);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} //模拟键盘双击
public void doubleClick(WebElement element){
waitFor(element);
logger.info("点击"+element.getText());
Actions actions=new Actions(driver);
actions.doubleClick(element).perform();
} //拖拽
public void dragAndDrop(WebElement source,WebElement target){
waitFor(source);
logger.info(source.getText()+"拖拽到"+target.getText());
Actions actions=new Actions(driver);
actions.dragAndDrop(source, target).perform();
} //悬浮
public void hover(WebElement element){
waitFor(element);
logger.info("悬浮"+element.getText());
Actions actions=new Actions(driver);
actions.moveToElement(element).perform();
} //判断元素是否存在
public boolean isExist(WebElement element)
{
try
{
waitFor(element);
element.isDisplayed();
return true;
}
catch (Exception e) {
return false;
}
} //等待元素消失不可见
public boolean waitForDisappear(WebElement element){
wait=new WebDriverWait(driver, 30, 1);
try {
wait.until(ExpectedConditions.invisibilityOf(element));
} catch (Exception e) {
return false;
}
return true;
} public void selectby(WebElement element,int index){
waitFor(element);
Select select=new Select(element);
select.selectByIndex(index);
} public void assertTrue(WebElement element){
wait=new WebDriverWait(driver, 30);
try {
wait.until(ExpectedConditions.elementToBeClickable(element));
} catch (Exception e) {
}
Assert.assertTrue(element.isDisplayed());
} //切换到某个元素所在的iframe下
public void switchToIframe(WebElement ele){
driver.switchTo().frame(ele);
} //切换回默认frame
public void switchToDefaultContent(){
driver.switchTo().defaultContent();
} //滚动到顶
public void scrollToTop(){
((JavascriptExecutor)driver).executeScript("document.documentElement.scrollTop=0");
} //滚动到底
public void scrollToBottom(){
((JavascriptExecutor)driver).executeScript("document.documentElement.scrollTop=10000");
} // @Override
// @BeforeClass
// public void setUp(){
// System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\datas\\chromedriver2.37.exe");
// driver=new ChromeDriver();
// driver.manage().window().maximize();
// driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
// driver.get(this.getUrl());
// } }

loginwithParas.java

package testcase.login;

import org.apache.log4j.Logger;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import common.basic;
import page.loginPage;
import utils.ReadCSV; /**
* 用例名:用戶登录
* 用例编号:AT-001
*/
public class loginWithParas extends basic {
private static Logger logger = Logger.getLogger(loginWithParas.class); @DataProvider(name = "loginData")
public static Object[][] words() throws Exception {
return ReadCSV.readCSV(System.getProperty("user.dir") + "\\datas\\loginData.csv");
} @Test(dataProvider="loginData")
public void loginWithPara(String username, String password, String result) {
logger.info(username+" "+password+" "+result); initBrowser();
loginPage=new loginPage(driver);
loginPage.username.sendKeys(username);
loginPage.password.sendKeys(password);
threadwait(1000);
click(loginPage.loginButton); //验证已停用账号
if (result.contains("停用")) {
Assert.assertTrue(isExist(loginPage.stopUserMessage));
//验证已停用账号
} else if(result.contains("用户名密码错误")){
Assert.assertTrue(isExist(loginPage.wrongPwd));
} else {
//验证其他不同类型帐号
threadwait(1000);
click(loginPage.personalCenter);
threadwait(1000);
logger.info("预期值:"+result);
logger.info("实际值:"+loginPage.nameInfo.getText());
Assert.assertTrue(loginPage.nameInfo.getText().contains(result));
} logout();
}
}

extentsreport优化测试报告

NoSuchElementException:检查页面元素的定位表达式是否正确,或尝试其他定位方式;查看页面是否加载延迟,设置等待时间;

NoSuchFrameException :检查元素是否frame里,是否已切换到元素的frame下,或切换回default content

ElementNotVisibleException:检查元素是否存在不可见属性的元素,可借助Javascript实现元素操作;检查是否操作速度过快,页面没加载出来

Cannot focus element:检查是否sendkeys非input元素,可用Action后focus输入

Actions actions = new Actions(driver);
actions.moveToElement(element);
actions.click();
actions.sendKeys(text);
actions.build().perform();

maven+selenium+java+testng+jenkins自动化测试的更多相关文章

  1. 自动化测试框架selenium+java+TestNG——配置篇

    最近来总结下自动化测试 selenium的一些常用框架测试搭配,由简入繁,最简单的就是selenium+java+TestNG了,因为我用的是java,就只是总结下java了. TestNG在线安装: ...

  2. selenium第一课(selenium+java+testNG+maven)

    selenium介绍和环境搭建 一.简单介绍 1.selenium:Selenium是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包 ...

  3. selenium+java+testNG+maven环境搭建

    一.简单介绍 1.selenium: Selenium是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE.Mozilla Fir ...

  4. Selenium+Java+TestNG环境配置

    1. JDK 2.eclipse+TestNG >TestNG安装.   Name:testng  Location:http://beust.com/eclipse.如图: 3.seleniu ...

  5. 搭建基于IDEA+Selenium+Java+TestNG+Maven+Jenkins+SVN的Web端UI自动化测试环境

    第一步:工具下载安装配置 JDK安装与配置 IDEA安装与配置 Maven安装与配置 Tomcat部署与配置 Jenkins部署与配置 Svn安装与配置 各浏览器驱动下载与配置 第二步:集成各个工具到 ...

  6. jenkins、ant、selenium、testng搭建自动化测试框架

    如果在你的理解中自动化测试就是在eclipse里面讲webdriver的包引入,然后写一些测试脚本,这就是你所说的自动化测试,其实这个还不能算是真正的自动化测试,你见过每次需要运行的时候还需要打开ec ...

  7. 自动化测试框架selenium+java+TestNG——读取csv文件

    读取csv文件可以直接读取,也可以使用javacsv.jar,后者比较简单,这个也可以变相认为是对表格的处理,我们可以在表格中做好数据,存储成csv格式的文件,后续对xlsx表格的操作抽个时间再记录下 ...

  8. 自动化测试框架selenium+java+TestNG——TestNG注解、执行、测试结果和测试报告

    TestNG是java的一个测试框架,相比较于junit,功能更强大和完善,我是直接学习和使用的TestNG就来谈下TestNG的一些特点吧. TestNG的特点 注解 TestNG使用Java和面向 ...

  9. 自动化测试框架selenium+java+TestNG——TestNG详解

    TestNG按顺序执行case package com.testngDemo; import org.testng.annotations.AfterClass; import org.testng. ...

随机推荐

  1. RDD之一:总体介绍

    摘要 本文提出了分布式内存抽象的概念——弹性分布式数据集(RDD,Resilient Distributed Datasets),它具备像MapReduce等数据流模型的容错特性,并且允许开发人员在大 ...

  2. PAT L3-008. 喊山(BFS)C4 初赛30分

    喊山(30 分) 喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤.呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的. ...

  3. Java-API-Package:org.springframwork.transaction.annotation

    ylbtech-Java-API-Package:org.springframwork.transaction.annotation 1.返回顶部 1. @NonNullApi @NonNullFie ...

  4. HTTP:HTTP清单

    ylbtech-HTTP:HTTP清单 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   作者:ylbtech出处:http://ylbt ...

  5. Unreal Engine 4 Radiant UI 入门教程(一)制作Radiant HUD

    请注意:本篇教程的编号是从零开始的,如果没有看第零篇教程,请前往学习. 本教程介绍如何制作Radiant HUD,这是指将网页元素直接加入到HUD中,效果为: 对应的网页元素为: 第一步: 将之前下载 ...

  6. How to Enabling and Diabling VxDMP devices for use with Oracle ASM

    Enable DMP support for ASM to make DMP devices visible to ASM as available disks To make DMP devices ...

  7. 部署和调优 1.3 pureftp部署和优化-1

    FTP 是 File Transfe Protocol(文件传输协议)的英文简称,而中文简称为 “文传协议” 用于 Internet 上的控制件的双向传输. 可以访问    www.pureftpd. ...

  8. mssql error 26

    右击数据库选择“方面”,将“RemoteAccessEnabled”属性设为“True”,点“确定”

  9. 提示crontab command not found的解决方法

    操作步骤   1. 确认crontab是否安装:   执行 crontab 命令如果报 command not found,就表明没有安装   2. 安装 crontab   执行 yum insta ...

  10. 面试题: 1天的java面试题 已看1

    1,自我介绍下,我直接说的项目经历,(哪年在哪个公司呆过) 2,问是否有带过团队的经历,我说去年带过一次. 3,Struts是单例模式还是多例模式?我先说单例模式,后说多例模式. Struts1是单例 ...