TestNG测试框架在基于Selenium进行的web自动化测试中的应用

简介: 转载请注明出自天外归云的博客园:http://www.cnblogs.com/LanTianYou/ TestNG+Selenium+Ant TestNG这个测试框架可以很好的和基于Selenium的web自动化测试结合在一起,实现把我们写好的自动化测试用例以自定义顺序执行。

转载请注明出自天外归云的博客园:http://www.cnblogs.com/LanTianYou/

TestNG+Selenium+Ant

TestNG这个测试框架可以很好的和基于Selenium的web自动化测试结合在一起,实现把我们写好的自动化测试用例以自定义顺序执行。下面分为十二步来对TestNG测试框架进行总结,包括环境的部署,从TestNG框架的几种常用方法,到与Ant结合来实现自动化测试。

第一步:创建项目

新建一个名为forTestNg的java project,然后创建一个libs文件夹,导入所有和Selenium相关的jar包:

第二步:安装TestNG

在Eclipse中点击Help->Install New Software,点击Add,Location填写“http://beust.com/eclipse”,然后点击OK:

之后勾选TestNG,点击Next进行安装即可:

之后点击Next:

点击Accept并Finish:

进行安装:

点击OK:

完成安装后点击Yes重启Eclipse:

第三步:部署TestNG的jar包

Eclipse重启后,可以在libs文件夹中发现多了一个TestNG的jar包:

选中libs文件夹下所有的jar包,右键->Build Path->Add to Build Path:

第四步:新建TestNG类

新建一个名为forTestNg的package:

按下“Ctrl+N”选中TestNG类,点击Next:

填写信息如下(选择Source folder,选择Package name,给你的TestNG测试类起一个Class name,勾选两个Annotations,给XML文件起个名字),点击Finish:

NewTest类代码如下(@BeforeMethod的方法将在每个@Test的方法执行前执行,@AfterMethod的方法将在每个@Test的方法执行后执行):

package forTestNg;

import org.testng.annotations.Test;

import userInfo.UserInfo;

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.AfterMethod;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class NewTest {
public WebDriver webDriver; UserInfo usrInfo = new UserInfo(); @Test public void testA() throws InterruptedException { waitForLinkText(webDriver, "登录"); webDriver.findElement(By.linkText("登录")).click(); waitForId(webDriver, "input1"); webDriver.findElement(By.id("input1")).sendKeys(usrInfo.usrName); webDriver.findElement(By.id("input2")).sendKeys(usrInfo.pwd); webDriver.findElement(By.id("signin")).click(); System.out.println("Login successfully."); } @Test public void testB() throws InterruptedException { waitForLinkText(webDriver, "登录"); webDriver.findElement(By.linkText("登录")).click(); waitForId(webDriver, "input1"); webDriver.findElement(By.id("input1")).sendKeys(usrInfo.usrName); webDriver.findElement(By.id("input2")).sendKeys(usrInfo.pwd); webDriver.findElement(By.id("signin")).click(); System.out.println("Login successfully."); } @BeforeMethod public void beforeMethod() { System.out.println("Before method."); webDriver = new FirefoxDriver(); String url = "http://cnblogs.com"; webDriver.get(url); System.out.println("Navigate successfully."); } @AfterMethod public void afterMethod() { System.out.println("After method."); webDriver.quit(); System.out.println("Quit successfully."); } private static void waitForId(WebDriver webDriver, String id) throws InterruptedException { try {
Thread.sleep(1000); webDriver.findElement(By.id(id)); }
catch (Exception e) { Logger log = Logger.getLogger("lavasoft"); log.setLevel(Level.INFO); log.info(e.toString()); } } private static void waitForLinkText(WebDriver webDriver, String linkText) throws InterruptedException { try {
Thread.sleep(1000); webDriver.findElement(By.linkText(linkText)); }
catch (Exception e) { Logger log = Logger.getLogger("lavasoft"); log.setLevel(Level.INFO); log.info(e.toString()); } } }

*第五步:新建辅助类

新建一个userInfo包,并创建一个UserInfo类,用于存储用户信息:

代码如下:

package userInfo;

public class UserInfo {
    public String usrName;
    public String pwd;

    public UserInfo() {
        usrName = "用户名";
        pwd = "密码";
    }
}

第六步:修改TestNG的xml配置文件

修改xmlTest.xml文件,内容如下(指定了测试方法的执行顺序):

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
    <test name="Test" preserve-order="true">
        <classes>
            <class name="forTestNg.NewTest" />
            <methods>
                <include name="testB" />
                <include name="testA" />
            </methods>
        </classes>
    </test> <!-- Test -->
</suite> <!-- Suite -->

以上代码指定了先执行方法testB,然后执行方法testA;

第七步:运行TestNG测试

在xml文件右键选择Run As->TestNG Suite运行测试:

运行结果如下,我们可以在Console中看到相应方法的测试结果:

从总结信息中可以看出,共运行了两个test方法,其中有一个失败了,我们可以看到是出现了locate不到link元素的异常,在“Results of running suite”栏下还可以看到测试结果是否通过的信息:

方法testB测试失败了,这是由于在方法testB里输入了乱码的linkText导致的:

@Test
public void testB() throws InterruptedException {
    waitForLinkText(webDriver, "登录");
    webDriver.findElement(By.linkText("登录")).click();
    waitForId(webDriver, "input1");
    webDriver.findElement(By.id("input1")).sendKeys(usrInfo.usrName);
    webDriver.findElement(By.id("input2")).sendKeys(usrInfo.pwd);
    webDriver.findElement(By.id("signin")).click();
    System.out.println("Login successfully.");
}

*、如果运行出错,提示找不到classpath——创建“TESTNG_HOME”环境变量,值为“D:\TestNG”(这里我把“testng-6.9.9.jar”这个jar包放在了D盘的这个路径下):

创建CLASSPATH环境变量,值为“%CLASSPATH%;%TESTNG_HOME%\testng-6.9.9.jar;”:

之后重启Eclipse并运行测试。

第八步:查看测试结果

进一步去看测试结果,首先找到项目所在的文件夹,发现有一个test-output的文件夹:

在其下的Suite文件夹下打开“Test.html”:

之后就可以看到测试结果了(红色的为失败,绿色的为通过):

第九步:测试多条case

当有多个classes需要测试的情况,这里拿两个classes举例,新创建一个class名为NewTest2,将上面NewTest类的代码复制粘贴进NewTest2类中,如下:

package forTestNg;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import userInfo.UserInfo;

public class NewTest2 {
public WebDriver webDriver;
    UserInfo usrInfo = new UserInfo();

    @Test
    public void testA() throws InterruptedException {
        waitForLinkText(webDriver, "登录");
        webDriver.findElement(By.linkText("登录")).click();
        waitForId(webDriver, "input1");
        webDriver.findElement(By.id("input1")).sendKeys(usrInfo.usrName);
        webDriver.findElement(By.id("input2")).sendKeys(usrInfo.pwd);
        webDriver.findElement(By.id("signin")).click();
        System.out.println("Login successfully.");
    }

    @Test
    public void testB() throws InterruptedException {
        waitForLinkText(webDriver, "登录");
        webDriver.findElement(By.linkText("登录")).click();
        waitForId(webDriver, "input1");
        webDriver.findElement(By.id("input1")).sendKeys(usrInfo.usrName);
        webDriver.findElement(By.id("input2")).sendKeys(usrInfo.pwd);
        webDriver.findElement(By.id("signin")).click();
        System.out.println("Login successfully.");
    }

    @BeforeMethod
    public void beforeMethod() {
        System.out.println("Before method.");
        webDriver = new FirefoxDriver();
        String url = "http://cnblogs.com";
        webDriver.get(url);
        System.out.println("Navigate successfully.");
    }

    @AfterMethod
    public void afterMethod() {
        System.out.println("After method.");
        webDriver.quit();
        System.out.println("Quit successfully.");
    }

    private static void waitForId(WebDriver webDriver, String id) throws InterruptedException {
        try {
            Thread.sleep(1000);
            webDriver.findElement(By.id(id));
        } catch (Exception e) {
            Logger log = Logger.getLogger("lavasoft");
            log.setLevel(Level.INFO);
            log.info(e.toString());
        }
    }

    private static void waitForLinkText(WebDriver webDriver, String linkText) throws InterruptedException {
        try {
            Thread.sleep(1000);
            webDriver.findElement(By.linkText(linkText));
        } catch (Exception e) {
            Logger log = Logger.getLogger("lavasoft");
            log.setLevel(Level.INFO);
            log.info(e.toString());
        }
    }
}

然后将xml文件进行修改,如下,修改了test的名字,将Test改为了Test1,并新加了Test2:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
    <test name="Test1" preserve-order="true">
        <classes>
            <class name="forTestNg.NewTest" />
            <methods>
                <include name="testB" />
                <include name="testA" />
            </methods>
        </classes>
    </test> <!-- Test -->
    <test name="Test2" preserve-order="true">
        <classes>
            <class name="forTestNg.NewTest2" />
            <methods>
                <include name="testA" />
                <include name="testB" />
            </methods>
        </classes>
    </test> <!-- Test -->
</suite> <!-- Suite -->

可以看出,在xmlTest.xml文件中新增了一个名为Test2的test,class的名字为forTestNg.NewTest2,里面的方法执行顺序为先testA后testB,和Test1中类的方法执行顺序正好相反。然后右键点击xmlTest.xml文件,选择Run As->TestNG Suite。之后测试就会自动按照先执行Test1再执行Test2的顺序进行了。Test1中先testB后testA,Test2中先testA后testB。从Console可以看出运行结果:

也可以从Results of running suite中查看测试的执行顺序和结果:

在项目的test-output\Suite文件夹下可以看到各个test的测试结果,每个test都对应有一个html格式的测试结果report:

第十步:忽略测试

忽略测试——被指定忽略的test方法在自动化执行测试的过程中将不被执行,即——被忽略,我们只需要修改想要忽略的test方法的Annotation信息。这里拿NewTest1和NewTest2这两个类中的testB方法举例,我们想要在执行过程中忽略执行方法testB,只需要将两个类中testB的Annotation信息修改如下:

@Test(enabled = false)
public void testB() throws InterruptedException {
    waitForLinkText(webDriver, "登录");
    webDriver.findElement(By.linkText("登录")).click();
    waitForId(webDriver, "input1");
    webDriver.findElement(By.id("input1")).sendKeys(usrInfo.usrName);
    webDriver.findElement(By.id("input2")).sendKeys(usrInfo.pwd);
    webDriver.findElement(By.id("signin")).click();
    System.out.println("Login successfully.");
}

这里,“@Test(enabled = false)”的意思就是让testB方法在执行过程中被忽略执行,也就是不执行的意思。再执行xmlTest.xml文件,我们可以从测试结果看出,这两个被指定忽略的方法并没有在本次测试中执行(两个类中都只执行了testA方法):

第十一步:组测试

组测试——顾名思义,就是将测试分组,测试是针对方法的测试,那么分组也是针对方法的分组。我们需要做的还是修改待测方法的Annotation与xmlTest.xml文件的内容。在NewTest类中修改待测方法的Annotation如下:

@Test(groups = {"loginTest"})
public void testA() throws InterruptedException {
    waitForLinkText(webDriver, "登录");
    webDriver.findElement(By.linkText("登录")).click();
    waitForId(webDriver, "input1");
    webDriver.findElement(By.id("input1")).sendKeys(usrInfo.usrName);
    webDriver.findElement(By.id("input2")).sendKeys(usrInfo.pwd);
    webDriver.findElement(By.id("signin")).click();
    System.out.println("Login successfully.");
}

@Test(groups = {"loginErrorTest"})
public void testB() throws InterruptedException {
    waitForLinkText(webDriver, "登录");
    webDriver.findElement(By.linkText("登录")).click();
    waitForId(webDriver, "input1");
    webDriver.findElement(By.id("input1")).sendKeys(usrInfo.usrName);
    webDriver.findElement(By.id("input2")).sendKeys(usrInfo.pwd);
    webDriver.findElement(By.id("signin")).click();
    System.out.println("Login successfully.");
}

在NewTest2类中修改待测方法的Annotation如下:

@Test(groups = { "loginTest" })
public void testA() throws InterruptedException {
    waitForLinkText(webDriver, "登录");
    webDriver.findElement(By.linkText("登录")).click();
    waitForId(webDriver, "input1");
    webDriver.findElement(By.id("input1")).sendKeys(usrInfo.usrName);
    webDriver.findElement(By.id("input2")).sendKeys(usrInfo.pwd);
    webDriver.findElement(By.id("signin")).click();
    System.out.println("Login successfully.");
}

public void testB() throws InterruptedException {
    waitForLinkText(webDriver, "登录");
    webDriver.findElement(By.linkText("登录")).click();
    waitForId(webDriver, "input1");
    webDriver.findElement(By.id("input1")).sendKeys(usrInfo.usrName);
    webDriver.findElement(By.id("input2")).sendKeys(usrInfo.pwd);
    webDriver.findElement(By.id("signin")).click();
    System.out.println("Login successfully.");
}

将NewTest和NewTest2这两个类中的BeforeMethod方法和AfterMethod方法也一同加进组里,否则会抛空指针异常:

@BeforeMethod(groups = { "loginTest", "loginErrorTest" })
public void beforeMethod() {
    System.out.println("Before method.");
    webDriver = new FirefoxDriver();
    String url = "http://cnblogs.com";
    webDriver.get(url);
    System.out.println("Navigate successfully.");
}

@AfterMethod(groups = { "loginTest", "loginErrorTest" })
public void afterMethod() {
    System.out.println("After method.");
    webDriver.quit();
    System.out.println("Quit successfully.");
}

对于组方法中调用的其他方法,我们不需要做处理(不需要把组方法中调用的方法也加进组)。

然后我们对xmlTest.xml文件进行修改,只保留一个test,将两个class都放进去。在test中增加groups,指定执行属于loginTest组的方法。修改如下:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite" parallel="false">
    <test name="Test" preserve-order="true">
        <groups>
            <run>
                <include name="loginTest" />
            </run>
        </groups>
        <classes>
            <class name="forTestNg.NewTest" />
            <class name="forTestNg.NewTest2" />
        </classes>
    </test> <!-- Test -->
</suite> <!-- Suite -->

之后我们再执行xmlTest.xml文件,结果如下:

我们可以看出,只有组方法(testA)才被执行了,不在组中的方法均没有被执行(组方法中调用的方法除外)。

第十二步:同Ant结合测试

同Ant的结合使用——首先下载一个Ant,解压缩zip文件,这里我将解压后的apache-ant-1.9.6文件夹放在“D:\”目录下:

之后要配置环境变量,仍然是:

1、创建一个环境变量叫ANT_HOME,值为路径“D:\apache-ant-1.9.6”;

2、修改Path变量,追加值“%ANT_HOME%\bin”;

3、修改CLASSPATH变量,追加值“%ANT_HOME%\lib”。

然后在Eclipse中项目上点击右键,选择Export:

然后选择General下的Ant Buildfiles->Next->Finish:

之后我们可以看到在项目的目录下,自动创建出了一个叫build.xml的文件:

 上述是告诉你怎么用Eclipse自动生成build.xml文件,然并卵,我们还是需要把如下的代码替换上去:

<project name="TestNGTest" default="test" basedir=".">

    <!-- Define <testng> task -->

    <taskdef name="testng" classname="org.testng.TestNGAntTask">
        <classpath>
            <pathelement location="libs/testng-6.9.9.jar" />
        </classpath>
    </taskdef>

    <property name="testdir" location="src/forTestNg" />
    <property name="srcdir" location="src" />
    <property name="libdir" location="libs" />
    <property name="full-compile" value="true" />

    <path id="classpath.base" />
    <path id="classpath.test">

        <fileset dir="${libdir}">
            <include name="**/*.jar" />
        </fileset>

        <pathelement location="${testdir}" />
        <pathelement location="${srcdir}" />

        <path refid="classpath.base" />
    </path>

    <target name="clean">
        <delete verbose="${full-compile}">
            <fileset dir="${testdir}" includes="**/*.class" />
        </delete>
    </target>

    <target name="compile" depends="clean">
        <javac srcdir="${srcdir}" destdir="${testdir}" verbose="${full-compile}">
            <classpath refid="classpath.test" />
        </javac>
    </target>

    <target name="test" depends="compile">
        <testng outputdir="${testdir}" classpathref="classpath.test">
            <xmlfileset dir="${srcdir}" includes="xmlTest.xml" />
        </testng>
    </target>

</project>

这里要非常注意:

1)修改taskdef中的location为testng jar包在项目中的相对路径,这里为“libs/testng-6.9.9.jar”;

2)修改property的值,这里修改了两处,一处是testdir的location,填写的是待测包的路径“src/forTestNg”。另一处是libdir的location,填写的是放jar包的路径“libs”;

3)最后一个target中xmlfileset的includes的值,我们要修改为“xmlTest.xml”,这是我们的TestNG xml文件的名字。

都改好后就可以在PowerShell中利用Ant来进行自动化测试了:

1)首先要cd到项目所在的路径下:

2)然后输入ant,执行测试:

但是我们注意到测试结果是失败的:

仔细看,可以发现是因为linkText的value乱码导致的,这是Ant编译时的中文乱码问题,需在build.xml文件中调用javac的地方加入encoding的参数值,解决方法如下:

<target name="compile" depends="clean">
    <javac encoding="utf-8" srcdir="${srcdir}" destdir="${testdir}" verbose="${full-compile}">
        <classpath refid="classpath.test" />
    </javac>
</target>

我们把compile这个target中的javac标签赋予了一个encoding参数,并赋值为“uft-8”,意即中文编码模式。这样就OK了,我们再输入ant,敲回车,执行测试:

测试全部通过啦~这就是使用Ant与TestNG一起来执行自动化测试的方法。

关于TestNG测试框架更多的用法,可以看这里,还有这里

相关文章
|
7天前
|
前端开发 JavaScript 关系型数据库
从前端到后端:构建现代化Web应用的技术探索
在当今互联网时代,Web应用的开发已成为了各行各业不可或缺的一部分。从前端到后端,这篇文章将带你深入探索如何构建现代化的Web应用。我们将介绍多种技术,包括前端开发、后端开发以及各种编程语言(如Java、Python、C、PHP、Go)和数据库,帮助你了解如何利用这些技术构建出高效、安全和可扩展的Web应用。
|
10天前
|
前端开发 Java 测试技术
《手把手教你》系列技巧篇(十二)-java+ selenium自动化测试-元素定位大法之By link text(详细教程)
【4月更文挑战第4天】本文介绍了link text在自动化测试中的应用。Link text是指网页中链接的文字描述,点击可跳转至其他页面。文章列举了8种常用的定位方法,其中着重讲解了link text定位,并通过实例展示了如何使用Java代码实现点击百度首页的“奥运奖牌榜 最新排名”链接,进入相应页面。如果link text不准确,则无法定位到元素,这说明linkText是精准匹配,而非模糊匹配。文章还提到了partial link text作为link text的模糊匹配版本,将在后续内容中介绍。
34 4
|
8天前
|
XML 前端开发 Java
《手把手教你》系列技巧篇(十四)-java+ selenium自动化测试-元素定位大法之By xpath上卷(详细教程)
【4月更文挑战第6天】按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath。xpath 的定位方法, 非常强大。使用这种方法几乎可以定位到页面上的任意元素。xpath 是XML Path的简称, 由于HTML文档本身就是一个标准的XML页面,所以我们可以使用Xpath 的用法来定位页面元素。XPath 是XML 和Path的缩写,主要用于xml文档中选择文档中节点。基于XML树状文档结构,XPath语言可以用在整棵树中寻找指定的节点。
41 0
|
1天前
|
数据库 开发者 Python
Python中使用Flask构建简单Web应用的例子
【4月更文挑战第15天】Flask是一个轻量级的Python Web框架,它允许开发者快速搭建Web应用,同时保持代码的简洁和清晰。下面,我们将通过一个简单的例子来展示如何在Python中使用Flask创建一个基本的Web应用。
|
2天前
|
监控 测试技术 API
深入理解自动化测试框架Selenium的设计与实现
【4月更文挑战第14天】在软件开发过程中,自动化测试是确保代码质量、减少人工重复劳动的关键步骤。Selenium作为一款广泛使用的自动化测试工具,提供了对多种浏览器和操作系统的支持。本文将探讨Selenium的核心组件及其架构设计,分析其如何通过WebDriver与浏览器交互,以及它如何支持多种编程语言进行脚本编写。同时,我们还将讨论Selenium Grid的作用以及它如何实现并行测试,以缩短测试周期并提高测试效率。
163 58
|
3天前
|
Web App开发 测试技术 网络安全
|
4天前
|
Web App开发 前端开发 Java
框架分析(11)-测试框架
框架分析(11)-测试框架
|
5天前
|
JavaScript 前端开发 API
Vue.js:构建高效且灵活的Web应用的利器
Vue.js:构建高效且灵活的Web应用的利器
|
5天前
|
前端开发 JavaScript Java
《手把手教你》系列技巧篇(十七)-java+ selenium自动化测试-元素定位大法之By css上卷(详细教程)
【4月更文挑战第9天】本文介绍了CSS定位方式的使用,包括它的优势和8种常用的定位方法。CSS定位相比XPath定位更快、更稳定。文章通过示例详细讲解了如何使用CSS定位元素,包括通过id、name、class name、tag name、link text、partial link text以及XPath进行定位。还提供了Java代码示例来演示如何在自动化测试中使用这些定位方法。
35 1
|
13天前
|
XML JSON JavaScript
使用JSON和XML:数据交换格式在Java Web开发中的应用
【4月更文挑战第3天】本文比较了JSON和XML在Java Web开发中的应用。JSON是一种轻量级、易读的数据交换格式,适合快速解析和节省空间,常用于API和Web服务。XML则提供更强的灵活性和数据描述能力,适合复杂数据结构。Java有Jackson和Gson等库处理JSON,JAXB和DOM/SAX处理XML。选择格式需根据应用场景和需求。