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

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介:

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:tbUsername
admin.loginbutton = loginForm:btnLogin
admin.events.createnewevent = adminHomeForm:_activitynew
admin.events.cancel = addEditEventForm:_IDcancel
admin.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/

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
1天前
|
安全 数据可视化 前端开发
【测试开发】用例篇 · 熟悉黑盒测试用例设计方法(2)· 正交表 · 场景设计 · 常见案例练习
【测试开发】用例篇 · 熟悉黑盒测试用例设计方法(2)· 正交表 · 场景设计 · 常见案例练习
5 0
|
1天前
|
人工智能 测试技术 数据处理
【测试开发】用例篇 · 熟悉黑盒测试用例设计方法(1)等价类划分法、边界值法、判定表法
【测试开发】用例篇 · 熟悉黑盒测试用例设计方法(1)等价类划分法、边界值法、判定表法
6 0
|
1天前
|
前端开发 Java 测试技术
selenium+python自动化测试--登录
selenium+python自动化测试--登录
7 2
|
1天前
|
测试技术 iOS开发
pytest Mark标记测试用例
使用`pytest.mark`进行测试用例分组和筛选,如`@pytest.mark.webtest`。通过`pytest -m`参数执行特定标记的用例,例如`pytest -s test_command_param.py -m webtest`。同时,pytest支持内置的skip、skipif和xfail功能来管理特殊用例:skip始终跳过,skipif条件满足时跳过,xfail则标记预期失败的测试。
5 0
|
1天前
|
Web App开发 缓存 前端开发
《手把手教你》系列技巧篇(四十四)-java+ selenium自动化测试-处理https 安全问题或者非信任站点-下篇(详解教程)
【5月更文挑战第8天】这篇文档介绍了如何在IE、Chrome和Firefox浏览器中处理不信任证书的问题。作者北京-宏哥分享了如何通过编程方式跳过浏览器的证书警告,直接访问不受信任的HTTPS网站。文章分为几个部分,首先简要介绍了问题背景,然后详细讲解了在Chrome浏览器中的两种方法,包括代码设计和运行效果,并给出了其他浏览器的相关信息和参考资料。最后,作者总结了处理此类问题的一些通用技巧。
16 2
|
1天前
|
Web App开发 JavaScript 前端开发
《手把手教你》系列技巧篇(四十三)-java+ selenium自动化测试-处理https 安全问题或者非信任站点-上篇(详解教程)
【5月更文挑战第7天】本文介绍了如何在Java+Selenium自动化测试中处理浏览器对不信任证书的处理方法,特别是针对IE、Chrome和Firefox浏览器。在某些情况下,访问HTTPS网站时会遇到证书不可信的警告,但可以通过编程方式跳过这些警告。
13 1
|
1天前
|
前端开发 Java 测试技术
《手把手教你》系列技巧篇(四十二)-java+ selenium自动化测试 - 处理iframe -下篇(详解教程)
【5月更文挑战第6天】本文介绍了如何使用Selenium处理含有iframe的网页。作者首先解释了iframe是什么,即HTML中的一个框架,用于在一个页面中嵌入另一个页面。接着,通过一个实战例子展示了在QQ邮箱登录页面中,由于输入框存在于iframe内,导致直接定位元素失败。作者提供了三种方法来处理这种情况:1)通过id或name属性切换到iframe;2)使用webElement对象切换;3)通过索引切换。最后,给出了相应的Java代码示例,并提醒读者根据iframe的实际情况选择合适的方法进行切换和元素定位。
9 0
|
1天前
|
数据采集 Web App开发 数据挖掘
利用Python和Selenium实现定时任务爬虫
利用Python和Selenium实现定时任务爬虫
|
1天前
|
JavaScript 前端开发 测试技术
Python Selenium基本用法
Python Selenium基本用法
38 2
|
1天前
|
Web App开发 数据采集 前端开发
基于Python的Selenium详解:从入门到实践
基于Python的Selenium详解:从入门到实践
122 0