Selenium自动化测试用例设计注意事项(二)

UI映射

  一个UI映射是一种机制,它存储所有的定位器的测试套件在一个地方,方便修改UI元素的路径标识符或改变在AUT。测试脚本,然后使用UI地图定位以被测试的元件。基本上,UI地图是一个存储库的测试脚本对象,对应于被测试的应用程序的UI元素。

  是什么让一个UI地图有帮助吗?其主要目的是测试脚本的管理更加容易。当定位需要编辑,有一个中央位置轻松地找到对象,而不是通过搜索测试脚本代码。此外,它允许改变的标识符在一个地方,而不是在多个地方,以使更改在测试脚本,或为此事,在多个测试脚本。

  总之,一个UI地图有两个显着的优点。

  ● UI对象使用一个集中的位置,而不是让他们分散在整个脚本。这使得脚本维护更高效。

  ● 神秘的HTML标识符和名称可以被赋予了更多的人类可读的名字,提高测试脚本的可读性。

  考虑下面很难理解的测试代码(Java语言)。

public void testNew() throws Exception {
             selenium.open(http://www.test.com);
             selenium.type("loginForm:tbUsername", "xxxxxxxx");
             selenium.click("loginForm:btnLogin");
             selenium.click("adminHomeForm:_activitynew");
             selenium.waitForPageToLoad("30000");
             selenium.click("addEditEventForm:_IDcancel");
             selenium.waitForPageToLoad("30000");
             selenium.click("adminHomeForm:_activityold");
             selenium.waitForPageToLoad("30000");
}

  该代码很难被那些不熟悉待测应用(AUT)页面源代码的人理解。即使是待测应用的固定用户可能也很难理解这段脚本代码的作用。一个更好的脚本可能是:

public void testNew() throws Exception {
             selenium.open(http://www.test.com);
             selenium.type(admin.username, "xxxxxxxx");
             selenium.click(admin.loginbutton);
             selenium.click(admin.events.createnewevent);
             selenium.waitForPageToLoad("30000");
             selenium.click(admin.events.cancel);
             selenium.waitForPageToLoad("30000");
             selenium.click(admin.events.viewoldevents);
             selenium.waitForPageToLoad("30000");
}

  使用备注和空格换行、再加上UI映射标识,下面的代码更加易读:

public void testNew() throws Exception {
 
             // Open app url.
             selenium.open(http://www.test.com);
 
             // Provide admin username.
             selenium.type(admin.username, "xxxxxxxx");
 
             // Click on Login button.
             selenium.click(admin.loginbutton);
 
             // Click on Create New Event button.
             selenium.click(admin.events.createnewevent);
             selenium.waitForPageToLoad("30000");
 
             // Click on Cancel button.
             selenium.click(admin.events.cancel);
             selenium.waitForPageToLoad("30000");
 
             // Click on View Old Events button.
             selenium.click(admin.events.viewoldevents);
             selenium.waitForPageToLoad("30000");
}

  有多种方法可以实现UI映射。可以创建一个类或结构体来存储字符串变量,每个变量存储一个定位信息。或者,使用一个文本文件来存储键值对。在Java中,一个包含键值对的属性property文件可能是最好的方法。

 考虑如下属性文件prop.properties,为上述代码例子中的UI元素指定了 “别名”:

admin.username = loginForm:tbUsernameadmin.loginbutton = loginForm:btnLoginadmin.events.createnewevent = adminHomeForm:_activitynewadmin.events.cancel = addEditEventForm:_IDcanceladmin.events.viewoldevents = adminHomeForm:_activityold

  其中定位信息还是指向页面的HTML对象,但我们在测试脚本和UI元素之间引入一层抽象层。测试类从属性文件中读取定位信息,从而实现UI映射。

  页面对象设计模式

  页面对象设计模式,可以提高自动化测试脚本的维护性、减少代码重复,越发流行。页面对象是一个面向对象的类,作为待测应用对外提供的接口。测试代码在需要和UI页面交互时,使用此页面对象类的方法。这样做的好处是,如果UI页面发生变化,测试代码本身并不需要改变,只需要改变相应的页面对象的代码。为适应新UI页面的所有更改,都位于一个地方。

  页面对象设计模式具有以下优点:

  1、测试代码和页面相关的代码,比如页面元素定位信息(若使用UI映射,也包括定位信息的应用),页面布局等,完全分离;

  2、可以维护单一的储存库来存储页面提供的服务或操作,而不是把他们分散在测试代码中。

  在这两种情况下,这使得任何由于UI界面变化导致的修改,都可以在一个地方进行修改。关于该技术的更多有用信息,可以在众多的博客上找到。我们也鼓励读者去阅读更多。 许多人写这样的设计模式和超出本用户指南的范围,可以提供有用的提示。不过,为了让你开始,我们将举例说明页面对象的一个简单的例子。

  首先,考虑一个例子,典型的自动化测试,不使用页面对象。

/***
 * Tests login feature
 */
public class Login {
 
        public void testLogin() {
                selenium.type("inputBox", "testUser");
                selenium.type("password", "my supersecret password");
                selenium.click("sign-in");
                selenium.waitForPageToLoad("PageWaitPeriod");
                Assert.assertTrue(selenium.isElementPresent("compose button"),
                                "Login was unsuccessful");
        }
}

  这种方法有两个问题。

  1、没有分离测试代码和待测应用的定位器(在这个例子中是ID);两者都交织在一个单一方法中。如果待测应用UI改变了它的标识,布局,或登录输入和处理的方式变化,测试代码本身必须改变。

  2、ID定位信息分散在多个测试代码中,所有的测试不得不使用此登录页面。

  使用页面对象技术,上述测试代码可以按如下方式重写,为登录页面的页面对象例子:

/**
 * Page Object encapsulates the Sign-in page.
 */
public class SignInPage {
 
        private Selenium selenium;
 
        public SignInPage(Selenium selenium) {
                this.selenium = selenium;
                if(!selenium.getTitle().equals("Sign in page")) {
                        throw new IllegalStateException("This is not sign in page, current page is: "
                                        +selenium.getLocation());
                }
        }
 
        /**
         * Login as valid user
         *
         * @param userName
         * @param password
         * @return HomePage object
         */
        public HomePage loginValidUser(String userName, String password) {
                selenium.type("usernamefield", userName);
                selenium.type("passwordfield", password);
                selenium.click("sign-in");
                selenium.waitForPageToLoad("waitPeriod");
 
                return new HomePage(selenium);
        }
}

 主页的页面对象可能会是这个样子:

/**
 * Page Object encapsulates the Home Page
 */
public class HomePage {
 
        private Selenium selenium;
 
        public HomePage(Selenium selenium) {
                if (!selenium.getTitle().equals("Home Page of logged in user")) {
                        throw new IllegalStateException("This is not Home Page of logged in user, current page" +
                                        "is: " +selenium.getLocation());
                }
        }
 
        public HomePage manageProfile() {
                // Page encapsulation to manage profile functionality
                return new HomePage(selenium);
        }
 
        /*More methods offering the services represented by Home Page
        of Logged User. These methods in turn might return more Page Objects
        for example click on Compose mail button could return ComposeMail class object*/
 
}

  现在,使用上述两个页面对象的登录测试代码,如下所示。

/***
 * Tests login feature
 */
public class TestLogin {
 
        public void testLogin() {
                SignInPage signInPage = new SignInPage(selenium);
                HomePage homePage = signInPage.loginValidUser("userName", "password");
                Assert.assertTrue(selenium.isElementPresent("compose button"),
                                "Login was unsuccessful");
        }
}

  怎么样使用页面对象进行设计有很大的灵活性,但也有一些基本的规则以保证得到测试代码具有所需的可维护性。页面对象本身不应该被验证或断言。这应该是测试的一部分,并应始终在测试代码中去验证或断言,而不要放在页面对象内。页面对象将包含页面展现,方法的形式表示页面提供的服务,但不需要包含应该在测试代码中维护的代码。

  唯一的应该存在页面对象中的验证方法是,验证页面、页面上的重要元素,被正确的加载。这这个验证应该在页面初始化时进行。在上面的例子中,SignInPage 和 HomePage 的构造函数检查了期望的页面是否可用,是否准备好接受测试代码的请求。

  页面对象并不一定要代表整个页面。页面对象设计模式可用于表示页面上组件。在待测应用上的一个页面若有多个组件,每个组件对应一个页面对象可以提高可维护性。

  在测试时,还会遇到其他的测试设计模式。有些人用一个页面工厂模式来实例化页面对象。讨论所有的这些测试模式,超出了本文档的的范围。在这里,我们只为大家介绍概念,使读者知道这些东西可以些什么。正如前面提到的,很多人都在博客上讨论这个话题,我们鼓励读者搜索这些话题。

  数据驱动测试

  数据驱动测试是指相同的测试(或测试集)可以使用不同的数据多次执行。这些数据集往往来自外部文件,如csv文件,文本文件,或者是从数据库加载。数据驱动测试是一种常用的自动化测试技术,使用不同的输入对应用程序进行多次验证。当测试被针对不同的数据进行设计时,所输入的数据就可以扩展,基本上不需要修改测试代码就可以进行更多的测试。

# Collection of String values
source = open("input_file.txt", "r")
values = source.readlines()
source.close()
# Execute For loop for each String in the values array
for search in values:
    sel.open("/")
    sel.type("q", search)
    sel.click("btnG")
    sel.waitForPageToLoad("30000")
    self.failUnless(sel.is_text_present("Results * for " + search))

 上面的Python代码打开一个文本文件,这个文件每行包含不同的搜索字符串。然后代码保存字符串到一个字符串数组,对数值进行遍历,使用搜索字符串进行查询,并进行断言。

  这是一个非常简单的例子,但其中的思路表明,可以很简单的使用编程、脚本语言进行数据驱动的测试。有关更多示例,请参阅 Selenium RC wiki 来了解如何从电子表格读取数据或使用TestNG的提供数据。此外,这是一个在自动化测试的专业人士圈内众所周知的话题之一,包括那些不使用Selenium的自动化圈子,因此搜索互联网上的“数据驱动测试”,会得到许多关于这一主题的博客。

  数据库验证

  另一种常见的测试类型是,比较用户界面上的数据和存储在后台数据库中的数据。因为你也可以使用一种编程语言进行数据库查询,假设你有数据库相关的函数,你可以用它们来检索数据,然后使用这些数据来验证页面上所显示的数据是正确的。

  考虑如下例子,从数据库中进行检索注册电子邮件地址,然后再和界面上的数据进行比较。代码如下,先建立一个数据库连接,并从数据库中检索数据,使用的是Java语言:

// Load Microsoft SQL Server JDBC driver.
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
 
// Prepare connection url.
String url = "jdbc:sqlserver://192.168.1.180:1433;DatabaseName=TEST_DB";
 
// Get connection to DB.
public static Connection con =
DriverManager.getConnection(url, "username", "password");
 
// Create statement object which would be used in writing DDL and DML
// SQL statement.
public static Statement stmt = con.createStatement();
 
// Send SQL SELECT statements to the database via the Statement.executeQuery
// method which returns the requested information as rows of data in a
// ResultSet object.
 
ResultSet result =  stmt.executeQuery
("select top 1 email_address from user_register_table");
 
// Fetch value of "email_address" from "result" object.
String emailaddress = result.getString("email_address");
 
// Use the emailAddress value to login to application.
selenium.type("userID", emailaddress);
selenium.type("password", secretPassword);
selenium.click("loginButton");
selenium.waitForPageToLoad(timeOut);
Assert.assertTrue(selenium.isTextPresent("Welcome back" +emailaddress), "Unable to log in for user" +emailaddress)

  这是一个简单的Java例子从数据库中检索数据。

====================================分割线================================

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-10-31 06:08:28

Selenium自动化测试用例设计注意事项(二)的相关文章

Selenium自动化测试用例设计注意事项(一)

自动化测试设计简介 我们在本章提供的信息,对自动化测试领域的新人和经验丰富的老手都是有用的.本篇中描述最常见的自动化测试类型, 还描述了可以增强您的自动化测试套件可维护性和扩展性的"设计模式".还没有使用这些技术的.有经验的自动化测试工程师会对这些技术更加感兴趣. 测试类型 您应该测试应用程序中的哪些部分?这取决于您的项目的各种影响因素:用户的期望,时间期限,项目经理设置的优先事项等等.但是,一旦项目边界定义完成,作为测试工程师,你必须做出要测试什么的决定. 为了对Web应用的测试类型

自动化测试用例设计

序言:自动化测试中,自动化测试用例是一个重点中的重点,个人以为,到底如何去定位自动化测试用例设计的 形式和发展是决定自动化测试成败的关键,根据一些研究和看法,我写了一个自动化测试用例设计的一个大概情况,当然一家之言而言,当然,大家在测试过程中, 接触过自动化测试的,肯定就接触过自动化测试用例,其是自动化测试脚本本身也是一种自动化测试用例,看看以下的情况大家遇到过么,希望大家有什么想法,提 出来吧. 一.自动化测试用例应用 手工测试用例是针对手工测试人员,自动化测试用 例是针对自动化测试框架,前者

CYQ.Data V5 分布式自动化缓存设计介绍(二)

CYQ.Data V5 分布式自动化缓存设计介绍(二) 前言: 最近一段时间,开始了<IT连>创业,所以精力和写的文章多数是在分享创业的过程. 而关于本人三大框架CYQ.Data.Aries.Taurus.MVC的相关文章,基本都很少写了. 但框架的维护升级,还是时不时的在进行中的,这点从开源的Github上的代码提交时间上就可以看出来了. 毕竟<IT连>的后台WebAPI,用的是Taurus.MVC,后台系统管理用的是Aries. 不过今天,就不写创业相关的文章了,先分享篇技术类

关于自动化软件测试用例设计的几点分析

1.手工测试用例和自动化测试用例功能定位的区别. a)手工测试用例 i.较好的异常处理能力,能通过人为的逻辑判断校验当前步骤的功能实现正确与否. ii.人工执行用例具有一定的步骤跳跃性. iii.人工测试步步跟踪,能够细致的定位问题. iv.主要用来发现功能缺陷 b)自动化测试用例 i.执行对象是脚本,任何一个判断都需要编码定义. ii.用例步骤之间关联性强. iii.主要用来保证产品主体功能正确完整和让测试人员从繁琐重复的工作中解脱出来. iv.目前自动化测试阶段定位在冒烟测试和回归测试. 2

JavaBean的任务和设计注意事项

一.JavaBean的任务:"Write once, run anywhere, reuse everywhere",即"一次性编写,任 何地方执行,任何地方重用".这个任何实际上就是要解决困扰软件工业的日益增加的复杂性,提供一个 简单的.紧凑的和优秀的问题解决方案. 1. 一个开发良好的软件组件应该是一次性地编写,而不需要再重新编写代码以增强或完善功能.因此 ,JavaBean应该提供一个实际的方法来增强现有代码的利用率,而不再需要在原有代码上重新进行编程. 除了

测试用例设计

等价类划分方法 一.方法简介 1.定义 把所有可能的输入数据,即程序的输入域划分成若干部分(子集),然后从每一个子集中选取少数具有代表性的数据作为测试用例.该方法是一种重要的,常用的黑盒测试用例设计方法.   2.划分等价类: 等价类是指某个输入域的子集合.在该子集合中,各个输入数据对于揭露程序中的错误都是等效的,并合理地假定:测试某等价类的代表值就等于对这一类其它值的测试,因此,可以把全部输入数据合理划分为若干等价类,在每一个等价类中取一个数据作为测试的输入条件就可以用少量代表性的测试数据取得

深色调网页界面设计注意事项

深色调的网站设计是比较流行的,它能营造出简洁.富有创造性的效果. 它能满足一些客户对网页设计风格的要求.然而,它并不能适用于每一个客户对网站设计风格的要求,设计师应根据实际情况而定. 尽管深色调的设计风格能做到引人注目的效果,但很多设计师不知道如果有效的使用它来打动.吸引浏览者. 深色调网页设计经常出现的问题是不易读.没有吸引力.很少打破传统的设计模式. 这片文章,我们将讨论一些如何让你的下一个深色调网页设计更能吸引.打动广大浏览者的方法和技巧,真正做到让你的设计表达你的创意. 最近的http:

测试用例设计——如何提高测试覆盖率

说到测试用例的设计,我想每个有过测试经历的测试工程师都会认为很简单,不就是:按需求或概要设计,得到软件功能划分图,然后据此按每个功能,采用等价类划分.临界值.因果图等方法来设计用例就行了. 但事实上撇开测试数据的设计不谈,仅就测试项来说,我们发现,对同一个项目,有经验的测试人员,在写用例或测试时总会有更多的测试考虑点,从而发现更多的问题:而有些测试人员测试用例的撰写却只有那么三板斧,表面看好象已经把页面所有信息的测试都考虑到了,实际上却还是遗漏了大量测试覆盖点,导致其测试出来的程序总是比较脆弱.

如何提高测试用例设计的测试覆盖率

说到测试用例的设计,我想每个有过测试经历的测试工程师都会认为很简单,不就是:按需求或概要设计,得到软件功能划分图,然后据此按每个功能,采用等价类划分.临界值.因果图等方法来设计用例就行了. 但事实上撇开测试数据的设计不谈,仅就测试项来说,我们发现,对同一个项目,有经验的测试人员,在写用例或测试时总会有更多的测试考虑点,从而发现更多的问题:而有些测试人员测试用例的撰写却只有那么三板斧,表面看好象已经把页面所有信息的测试都考虑到了,实际上却还是遗漏了大量测试覆盖点,导致其测试出来的程序总是比较脆弱.