目标实现:
1.自动登录测试帐号
2.自动进行Single Sign On登录测试
3.登录失败的能够截图保存
4.测试报告中能够详尽展出测试数据以及测试结果
一、项目结构:
(1)base包:用来存放元素对象,将测试的元素对象插入数据库中保存,好用来做为测试用例维护。
ObjectTest.java
package com.annie.base;
import java.util.Date;
public class ObjectTest {
private int id;
private String website;
private String page;
private String area;
private String object_type;
private String object_key_type;
private String object_pagename;
private String object_key;
private String description;
private String status;
private Date createtime;
private String createuser;
private Date updatetime;
private String updateuser;
private Date deletetime;
private String deleteuser;
//后面省去get/set方法
}
(2)util包:用来存放工具类,比如ExelData这样的工具类
(注意1.exel测试数据文档的路径;2.exel测试数据文档名;3.exel测试数据文档的testcase名,即sheet名)
package com.annie.util;
import java.io.File;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import jxl.*;
public class ExcelData implements Iterator<Object[]> {
private Workbook book = null;
private Sheet sheet = null;
private int rowNum = 0;
private int curRowNo = 0;
private int columnNum = 0;
private String[] columnnName;
public ExcelData(String filepath, String casename) {
try {
File directory = new File(".");
String ss = "open.anniewang.exceldata.";
book = Workbook.getWorkbook(new File(directory.getCanonicalPath()
+ "\\resources\\"
+ ss.replaceAll("\\.", Matcher.quoteReplacement("\\"))
+ filepath + ".xls"));
this.sheet = book.getSheet(casename);
this.rowNum = sheet.getRows();
Cell[] c = sheet.getRow(0);
this.columnNum = c.length;
columnnName = new String[c.length];
for (int i = 0; i < c.length; i++) {
columnnName[i] = c[i].getContents().toString();
}
this.curRowNo++;
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public boolean hasNext() {
if (this.rowNum == 0 || this.curRowNo >= this.rowNum) {
try {
book.close();
} catch (Exception e) {
e.printStackTrace();
}
return false;
} else
return true;
}
@Override
public Object[] next() {
Cell[] c = sheet.getRow(this.curRowNo);
Map<String, String> s = new TreeMap<String, String>();
for (int i = 0; i < this.columnNum; i++) {
String temp = "";
try {
temp = c[i].getContents().toString();
} catch (ArrayIndexOutOfBoundsException ex) {
temp = "";
}
s.put(this.columnnName[i], temp);
}
Object r[] = new Object[1];
r[0] = s;
this.curRowNo++;
return r;
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove unsupported.");
}
}
(3)testng包:用来存放公共的方法实现“高内聚,低耦合”的初衷(需要后面完善)
package com.annie.testng;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import com.annie.util.ExcelData;
;
public class TestNG {
private WebDriver driver;
@Parameters({ "browser" })
@BeforeTest
public void setupBrowser(String browser) {
if (browser.equals("firefox")) {
driver = new FirefoxDriver();
} else {
driver = new ChromeDriver();
}
}
@Parameters({ "url", "keyword" })
@Test
public void search(String url, String keyword) {
driver.get(url);
WebElement element = driver.findElement(By.name("q"));
element.sendKeys(keyword);
element.submit();
Assert.assertTrue(driver.getTitle().contains(keyword),
"Title is wrong!");
}
// 传入登录用户名、密码,获取元素,验证空用户/密码登录
@Parameters({ "url", "login_name_txtUserName", "login_name_txtPwd",
"login_name_btnLogin" })
// 参数: URL、用户名name、密码name、登陆按钮name
@Test(groups = { "login" })
public void login_username_empty(String login_name_txtUserName,
String login_name_txtPwd, String login_name_btnLogin)
throws Exception {
System.out.print("login_username_empty");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.findElement(By.name(login_name_txtUserName)).clear();
driver.findElement(By.name(login_name_txtPwd)).clear();
driver.findElement(By.name(login_name_txtUserName)).sendKeys("");
driver.findElement(By.name(login_name_txtPwd)).sendKeys("");
driver.quit();
}
}
(4)testcase包:用来存放编写的测试用例
LoginTest.java
package com.annie.testcase;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.annie.testng.TestNG;
import com.annie.util.ExcelData;
import com.annie.util.ScreenShot;
public class LoginTest {
private WebDriver driver;
private String username = "";
private String password = "";
private String URL = "http://10.0.0.88:8080/bkredcoil/web/index.html";
TestNG tn = new TestNG();
@DataProvider(name = "accounts")
// 登录用户的账户Excel,返回的是Object数组
public Iterator<Object[]> data() throws Exception {
return (Iterator<Object[]>) new ExcelData("accounts_login", "testA");
}
public void prmap(Map<String, String> arr) throws Exception {
driver = new FirefoxDriver();
// driver.get("http://redcoil.technologystudios.com/index.html");
driver.get("http://10.0.0.88:8080/bkredcoil/index.html");
// driver.get("http://10.0.0.88:8080/bkredcoil/controller/security/signon?sid=");
driver.manage().timeouts().implicitlyWait(500, TimeUnit.SECONDS);
driver.findElement(By.id("username")).clear();
driver.findElement(By.id("password")).clear();
Set<String> set = arr.keySet();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String s = (String) it.next();
if (s.equals("Email")) {
username = arr.get(s);
password = "";
} else {
password = arr.get(s);
}
if ((username.length() > 0) && (password.length() > 0)) {
System.out.println("username:" + username);
System.out.println("password:" + password);
if (driver.findElement(By.id("username")).getText().length() == 0) {
driver.findElement(By.id("username")).clear();
driver.findElement(By.id("username")).sendKeys(username);
}
if (driver.findElement(By.id("password")).getText().length() == 0) {
driver.findElement(By.id("password")).clear();
driver.findElement(By.id("password")).sendKeys(password);
}
driver.findElement(By.id("btn-login")).click();
Thread.sleep(500);
//登录成功后页面跳转,需要判断是否跳转到成功页面
String current_url = driver.getCurrentUrl();
System.out.println(current_url);
if (current_url.equals(URL)) {
//如果成功,则点击登录并退出driver
driver.get(URL);
System.out.println(driver.getCurrentUrl());
Thread.sleep(500);
System.out.println("Login Success!");
/* System.out.println(driver.findElement(By.id("button-1016"))
.getTagName());*/
driver.findElement(By.id("button-1016")).click();
driver.close();
} else {
// Thread.sleep(500);
//如果Login失败, 判断登录失败的对话框是否出现,如果出现warning则截图保存至screenpic文件夹下
if (driver.findElement(By.className("toast-item-wrapper"))
.isEnabled()) {
System.out.println("login_warning is show!");
ScreenShot ss = new ScreenShot();
ss.cutshot(driver);
driver.quit();
}
// 登录成功后跳转,重新获取URL
}
}
}
}
// 写一个类似prmap的方法,将Map类型的exel数据传入,并在指定的URL进行登录,将Map中的Email和password 做参数传入登陆即可
@Test(dataProvider = "accounts")
public void ts(Map<String, String> data) throws Exception {
this.prmap(data);
// 每次打印一组account,则调用登录用例
System.out.println("=====over=====");
System.out.println("");
}
}
Single Sign On 只需更改testng.xml
LoginTestURL.java
package com.annie.testcase;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.annie.testng.TestNG;
import com.annie.util.ExcelData;
import com.annie.util.ScreenShot;
public class LoginTestURL {
private WebDriver driver;
// private String username, password;
private String sid,url;
TestNG tn = new TestNG();
@DataProvider(name = "accounts")
// 登录用户的账户Excel,返回的是Object数组
public Iterator<Object[]> data() throws Exception {
return (Iterator<Object[]>) new ExcelData("accounts_login",
"BKID");
}
public void prmap(Map<String, String> arr) throws Exception {
driver = new FirefoxDriver();
// driver.get("http://redcoil.technologystudios.com/index.html");
// driver.get("http://10.0.0.88:8080/bkredcoil/index.html");
/*
* driver.findElement(By.id("username")).clear();
* driver.findElement(By.id("password")).clear();
*/
Set<String> set = arr.keySet();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String sid = (String) it.next();
/*
* if (s.equals("Email")) { username = arr.get(s); } else { password
* = arr.get(s); }
*/
System.out.println(arr.get(sid));
url="http://10.0.0.88:8080/bkredcoil/controller/security/signon?sid="+arr.get(sid);
System.out.println(url);
driver.get(url);
driver.manage().timeouts().implicitlyWait(500, TimeUnit.SECONDS);
/*
* if (driver.findElement(By.id("username")).getText().length()==0)
* { driver.findElement(By.id("username")).clear();
* driver.findElement(By.id("username")).sendKeys(username); } if
* (driver.findElement(By.id("password")).getText().length()==0) {
* driver.findElement(By.id("password")).clear();
*
*
*
* driver.findElement(By.id("btn-login")).click();
*/
driver.manage().timeouts().implicitlyWait(500, TimeUnit.SECONDS);
Thread.sleep(500);
driver.findElement(By.id("button-1056-btnInnerEl")).click();
driver.close();
// ScreenShot ss = new ScreenShot();
// try{
// ss.cutshot(driver);
// }
// catch(Exception e){
// e.printStackTrace();
//
// }
}
}
// 写一个类似prmap的方法,将Map类型的exel数据传入,并在指定的URL进行登录,将Map中的Email和password 做参数传入登陆即可
@Test(dataProvider = "accounts")
public void ts(Map<String, String> data) throws Exception {
this.prmap(data);
// 每次打印一组account,则调用登录用例
System.out.println("=====over=====");
System.out.println("");
}
}
testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
<test name="LoginTest" preserve-order="true">
<classes>
<class name="com.annie.testcase.LoginTest"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
build.xml
<project name="TestNGTest" default="testoutput" basedir=".">
<!-- Define <testng> task -->
<taskdef name="testng" classname="org.testng.TestNGAntTask">
<classpath>
<pathelement location="lib/testng-6.8.jar" />
</classpath>
</taskdef>
<property name="testoutputdir" location="test-output" />
<property name="srcdir" location="src" />
<property name="libdir" location="lib" />
<property name="full-compile" value="true" />
<property name="basedir" value="D:/workspace/BKRedcoil_TestCase/" />
<path id="classpath.test">
<fileset dir="${libdir}">
<include name="**/*.jar" />
</fileset>
<pathelement location="${testoutputdir}" />
<pathelement location="${srcdir}" />
</path>
<target name="clean">
<delete dir="${basedir}/bin" />
</target>
<target name="compile" depends="clean">
<mkdir dir="${basedir}/bin" />
<javac srcdir="${srcdir}" encoding="UTF-8" destdir="${basedir}/bin" verbose="${full-compile}" classpathref="classpath.test" includeantruntime="off" debug="on" debuglevel="lines,vars,source" />
</target>
<path id="classes">
<fileset dir="${libdir}" includes="*jar"/>
<fileset dir="${libdir}" includes="*zip"/>
<pathelement location="${basedir}/bin/"/>
</path>
<target name="runtest" depends="compile">
<testng outputdir="${testoutputdir}" classpathref="classes" delegateCommandSystemProperties="true">
<xmlfileset dir="${srcdir}" includes="testng.xml" />
</testng>
</target>
<target name="testoutput" depends="runtest">
<xslt in="${testoutputdir}/testng-results.xml" style="${testoutputdir}/testng-results.xsl" out="${testoutputdir}/index.html ">
<param name="testNgXslt.outputDir" expression="D:/workspace/BKRedcoil_TestCase/test-output/" />
<classpath refid="classpath.test" />
</xslt>
</target>
</project>
则执行后,会不断打开页面进行exel表格中的账户登录accounts_login.xls(sheet name is testA )
测试报告在test-output文件夹中生成
打开默认生成的测试报告(后面会美化测试报告步骤)
screenpic文件夹下自动保存登录失败的截图:
未完待续
需要解决:
1.登录失败如何设计测试用例,以及在report中展现fail的个例
2.如何维护测试用例(面向对象的设计)
该博客旨在实现Selenium Webdriver自动化测试,包括BKredcoil网站的自动登录和Single Sign On功能。内容涉及如何通过TestNG和ANT配合Excel数据驱动进行测试,同时在登录失败时自动截图并生成详细的测试报告。测试用例存储在Excel文档中,执行后会在特定文件夹下生成测试报告和失败截图。





610

被折叠的 条评论
为什么被折叠?



