自动化测试(8) | Selenium Java WebDriver 基础

WebDriver基础

欢迎阅读WebDriver基础讲义。本篇讲义将会重点介绍Selenium WebDriver的环境搭建和基本使用方法。

WebDriver环境搭建

Selenium WebDriver 又称为 Selenium2。

Selenium 1 + WebDriver = Selenium 2

WebDriver是主流Web应用自动化测试框架,具有清晰面向对象 API,能以最佳的方式与浏览器进行交互。

支持的浏览器:

  • Mozilla Firefox
  • Google Chrome
  • Microsoft Internet Explorer
  • Opera
  • Safari
  • Apple iPhone
  • Android browsers

Python + Selenium 环境搭建步骤

在上一篇中,我们已经确认使用Python来进行WebDriver的编码和操作。事实上Python+Selenium WebDriver环境的搭建分为两个部分:

  1. 安装python
  2. 安装Selenium

标准的安装步骤

  1. 选择Python的版本。

    Python主流的有两个大的版本,2.7和3.5(请注意,从Python的3.5版本开始,不再支持Windows XP操作系统,Windows XP用户请安装3.4版本)。我们的例子将会选用面向未来的3.x版本。

  2. 安装Python。

    在Python的官网(https://www.python.org/)下载最新的安装包,进行界面安装。

    安装的时候,推荐选择“Add exe to path”,将会自动添加Python的程序到环境变量中。

    • 安装3.4.3:

      Snap4.jpg
    • 安装3.5.2:

      Snap5.jpg

    然后可以在命令行输入python -V检测安装的Python版本。

    当前的版本安装中将会默认已经安装了setuptoolspip这两个Python的基本工具。如果使用了比较旧的Python版本的话,需要自行安装这两个工具。

    • setuptools:Python的基础工具包,用来构建、安装卸载Python程序
    • pip:Python软件包的安装和管理工具。通过pip可以简单的安装Python的任意类库
  3. 安装Selenium2.0版本。

    在Windows安装Selenium2.0,有两种途径。使用pip命令行或者源码安装。以下两种方法,使用任何一个均可。推荐pip的方式。

    1. 方法一:pip命令行安装,运行 | cmd,打开命令行,-U其实就是--upgrade,升级安装。用==2.53.6下载指定的2.53.6版本

      pip install selenium==2.53.6
      

      如果在windows 7 以上的电脑中,可以直接安装最新版,目前是3.0.2

      pip install selenium -U
      # 或者
      pip install selenium --upgrade
      

    2. 方法二:源码解压安装,前往https://pypi.python.org/pypi/selenium下载最新版(指定的2.53.6)的PyPI版本的Selenium,解压后执行

      1. 打开 https://pypi.python.org/pypi/selenium/2.53.6#downloads
      2. 下载 selenium-2.53.6.tar.gz (md5)
      3. 执行命令
      python setup.py install
      

Python 环境搭建示例

  1. 安装Python,检查Python的版本,3.x

  2. 启动 cmd

  3. 输入 pip install selenium==2.53.6
    如果无法连接互联网,需要先别的电脑下载Selenium,
    然后手动安装

    1. 访问 https://pypi.python.org/pypi/selenium/2.53.6#downloads
    2. 下载selenium-2.53.6.tar.gz
    3. 解压selenium-2.53.6.tar.gz 到 c:\selenium
    4. 进入解压后的目录 cd c:\selenium\selenium-2.53.6
    5. python setup.py install
  4. 安装 Firefox 火狐,必须是46.0以及以下,禁止自动更新。

  5. 安装 Selenium IDE:https://addons.mozilla.org/en-US/firefox/addon/selenium-ide/(用火狐打开)

  6. 第一个测试脚本

    1. 用PyCharm创建一个项目 autopyse

    2. 添加一个Python文件,first_test

    3. 写入一下脚本:

      from selenium import webdriver
      
      driver = webdriver.Firefox()
      driver.get("http://172.31.95.220/ranzhi")
      
    4. 右键该脚本,运行 first_test,会自动打开火狐,访问然之。

Java + Selenium + Maven 环境搭建步骤

接下来,我们使用Java+Selenium WebDriver 来进行环境的搭建,同样分为两个部分:

  1. 安装Java 和 intellij IDEA
  2. 引入指定Selenium的 Maven使用的pom.xml文件

Maven 是一个用于项目构建的工具,通过它便捷的管理项目的生命周期。同时 Maven 不只是一个简单的项目构建工具,还是一个依赖管理工具和项目信息管理工具。它提供了中央仓库,能帮我们自动下载构建。

标准的安装步骤

  1. 选择Java的版本并安装 Java 1.8

  2. 使用IDEA新建Project

    • New Project | Maven Project

      • GroupIdorg.seleniumhq.selenium
      • ArtifactId:selenium-parent
      • Version:2.53.1
    • 复制 下列xml文件selenium-pom.xml的内容到pom.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns="http://maven.apache.org/POM/4.0.0"
               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>
          <parent>
              <groupId>org.seleniumhq.selenium</groupId>
              <artifactId>selenium-parent</artifactId>
              <version>2.53.1</version>
          </parent>
          <artifactId>selenium-server</artifactId>
          <name>selenium-server</name>
          <dependencies>
              <dependency>
                  <groupId>org.seleniumhq.selenium</groupId>
                  <artifactId>selenium-java</artifactId>
                  <version>${project.version}</version>
              </dependency>
              <dependency>
                  <groupId>org.seleniumhq.selenium</groupId>
                  <artifactId>selenium-remote-driver</artifactId>
                  <version>${project.version}</version>
              </dependency>
              <dependency>
                  <groupId>commons-io</groupId>
                  <artifactId>commons-io</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.apache.commons</groupId>
                  <artifactId>commons-exec</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.testng</groupId>
                  <artifactId>testng</artifactId>
                  <version>6.8</version>
              </dependency>
          </dependencies>
          <build>
              <resources>
                  <resource>
                      <directory>src/main/resources</directory>
                  </resource>
              </resources>
          </build>
      </project>
      

开始使用WebDriver

在使用WebDriver之前,我们需要先做一些语言的背景学习。主要包括面向对象的理念、Python的基本使用以及Java的基本使用几个部分。

  • 面向对象的理念

    类,Class,指的是一个模板,一种设计模板。

    • 对象:对象是类的一个实例,有状态行为。例如,一只熊猫是一个对象,它的状态有:名字、年龄、性别;行为有:卖萌、吃竹子等。

      • 状态:成员变量
      • 行为:方法
    • :类是一个模板,一张图纸,它描述一类对象的行为和状态,把这个模板或图纸实现以后,就是一个对象。

  • Python的使用

    PyCharm工具是Python的编程工具,.py文件是Python的扩展名。

    Python的文件使用 xxx_xxx.py的方式命名,单词全部小写,中间用下划线加入。

    关于Python的学习,可以参考以下两个课程:

  • Java的使用

    intellij IDEA工具是Java的编程工具。

    Java的文件使用XxxYyy.java的大骆驼方式命名,单词的第一个字母大写。

    关于Java的学习,可以参考以下两个课程:

Python语言编写

接下来我们尝试几个简单的例子来体会一下Selenium WebDriver的使用。

Python 示例1

## 引入WebDriver的包
from selenium import webdriver

## 创建浏览器对象
browser = webdriver.Firefox()

## 打开百度网站
browser.get('https://www.baidu.com/')

Python 示例2

## 引入WebDriver包
from selenium import webdriver

## 引入WebDriver Keys包
from selenium.webdriver.common.keys import Keys

## 创建浏览器对象
browser = webdriver.Firefox()

## 导航到百度主页
browser.get('https://www.baidu.com')

## 检查标题是否为‘百度一下,你就知道’
assert '百度一下,你就知道' in browser.title

## 找到名字为wd的元素,赋值给elem
elem = browser.find_element_by_name('wd')  # 找到搜索框
elem.send_keys('seleniumhq' + Keys.RETURN)  # 搜索seleniumhq

## 关闭浏览器
browser.quit()

Python 使用类的方式进行自动化测试脚本的编写

from selenium import webdriver

__author__ = 'Administrator'


class RanzhiTest(object):
    def login(self):
        ## 声明一个变量,用来存Base URL,可以拼接成其他地址
        base_url = "http://172.31.95.220/ranzhi/www"

        ## 声明一个变量,用来存Firefox()的实例化对象
        driver = webdriver.Firefox()

        ## 用driver打开网页,登录页面
        driver.get(base_url)

        ## 查找“输入用户”的输入框,
        ## 并且清除已经存在的输入数据,重新输入用户“admin”
        driver.find_element_by_id("account").clear()
        driver.find_element_by_id("account").send_keys("admin")

        ## 查找“输入密码”的输入框,
        ## 并且清除已经存在的输入数据,重新输入密码“123456”
        driver.find_element_by_id("password").clear()
        driver.find_element_by_id("password").send_keys("123456")

        ## 查找登录的按钮,点击登录
        driver.find_element_by_id("submit").click()


if __name__ == "__main__":
    ranzhi_test = RanzhiTest()
    ranzhi_test.login()

上述用例,也可以去掉类,直接用面向过程的方式进行运行

from selenium import webdriver

__author__ = 'Administrator'

## 声明一个变量,用来存Base URL,可以拼接成其他地址
base_url = "http://172.31.95.220/ranzhi/www"

## 声明一个变量,用来存Firefox()的实例化对象
driver = webdriver.Firefox()

## 用driver打开网页,登录页面
driver.get(base_url)

## 查找“输入用户”的输入框,
## 并且清除已经存在的输入数据,重新输入用户“admin”
driver.find_element_by_id("account").clear()
driver.find_element_by_id("account").send_keys("admin")

## 查找“输入密码”的输入框,
## 并且清除已经存在的输入数据,重新输入密码“123456”
driver.find_element_by_id("password").clear()
driver.find_element_by_id("password").send_keys("123456")

## 查找登录的按钮,点击登录
driver.find_element_by_id("submit").click()

下面的例子,使用了禅道进行,同样是Python使用类的方式进行访问

from time import sleep
from selenium import webdriver

__author__ = 'Administrator'

class ZentaoTest(object):

    def login(self):

        ## 设定一个base url,存储根目录的地址
        base_url = "http://172.31.95.220/zentaopms/www"

        ## 实例化火狐浏览器的对象
        driver = webdriver.Firefox()

        ## 用get的方式,打开base url
        driver.get(base_url)

        ## 让python休息2秒钟,给火狐2秒时间加载页面
        sleep(2)

        ## 查找登录页面的用户输入框,并把元素保存到account中
        account = driver.find_element_by_id("account")

        ## 清除 account 已经输入的字符,并输入 admin
        account.clear()
        account.send_keys("admin")

        ## 查找登录页面的密码输入框,并把元素保存到 password 中
        password = driver.find_element_by_name("password")

        ## 清除 password 已经输入的字符,并输入 123456
        password.clear()
        password.send_keys("123456")

        ## 查找 保持登录 的元素(复选框),并打勾
        driver.find_element_by_id("keepLoginon").click()

        ## 查找 登录 的元素,点击登录
        driver.find_element_by_id("submit").click()

        ## 让python休息5秒钟,给火狐5秒时间加载页面
        sleep(5)

        ## 退出火狐浏览器
        driver.quit()


## 主方法的入口
if __name__ == "__main__":

    ## 实例化一个ZentaoTest对象,调用它登录的方法
    ZentaoTest().login()

XAMPP的安装部署和环境搭建

XAMPP的安装,在Windows操作系统中比较简单,可以直接运行安装文件,默认全部下一步,即可完成软件的安装。

请注意:Windows XP系统只能可以 XAMPP 1.8.2版本;Windows 7以及以上的系统可以安装最新版的XAMPP。XAMPP不分32位和64位操作系统。

XAMPP的安装

XAMPP的安装,在Windows操作系统中比较简单,可以直接运行安装文件,默认全部下一步,即可完成软件的安装。

请注意:Windows XP系统只能可以 XAMPP 1.8.2版本;Windows 7以及以上的系统可以安装最新版的XAMPP。XAMPP不分32位和64位操作系统。

安装的具体步骤:

  1. 双击 xampp-win32-1.8.2-6-VC9-installer.exe 进行安装 XAMPP,一直按 next,如果遇到问题,说 C:\xampp 不为空,可以换个地址,比如 C:\xampp2

  2. 安装完毕以后,打开 XAMPP Control Pannel

    1. 方法一:安装完毕以后,勾选 Open Control Pannel,然后点击 Finish
    2. 方法二:开始菜单 | XAMPP | XAMPP Control Pannel
  3. 开启 XAMPP的前两个应用程序,点击 Start,当 Start 变成 Stop,就打开了。

    1. Apache

    2. MySQL

      Snap1.jpg
  4. 点击右边的 Explorer按钮,打开目录,进入 htdocs

  5. 复制 ranzhi.2.5.zipC:\xampp\htdocs(也就是 第四步 进入的 目录)

  6. 解压 ranzhi.2.5.zip到 当前目录:C:\xampp\htdocs

    Snap2.jpg
  7. 打开浏览器,输入 "http://localhost/ranzhi",进行下一步安装

    1. 如果使用 VMware Workstation 安装网站,需要安装 firefox (Firefox_46.0.1.5966_setup.exe
    2. 如果使用 VMware Workstation 解压文件,需要安装 7zip,(类似 WinRar,安装 7zip1604.msi)
  8. 打开浏览器 安装然之

    Snap3.jpg
    Snap4.jpg
    Snap5.jpg
    Snap6.jpg
    Snap7.jpg
    Snap8.jpg
  9. 以后可以输入 "http://localhost/ranzhi/www" 打开网站。

XAMPP的部署

XAMPP = OS + Apache + MySQL + PHP + Perl

我们一般部署的网站,符合XAMPP环境的话,只需要启动Apache和MySQL两个应用。

部署步骤

  1. 启动Apache

  2. 启动MySQL

  3. 解压网站源文件,例如解压然之:ranzhi.2.5.zip,请把压缩包里面的ranzhi这个文件夹解压出来;禅道也类似,需要把压缩包中的zentaopms文件夹解压出来

  4. 部署源文件,请将解压以后的源文件放到xampp\htdocs文件夹中

  5. 通过浏览器访问部署好的网站源文件,进行向导安装。http://localhost/ranzhi/www

    PS:这里我们主要支持的是PHP+MySQL开发的网站部署。

XAMPP的问题解决

  • 无法启动Apache:请认真查看日志,判断80和443端口被什么样的程序占用,需要关闭对应程序,或者修改Apache的端口。
  1. IIS:控制面板 | 管理工具 | Internet信息服务 | 默认网站 | 关闭
  2. VisualSVN Server: 控制面板 | 管理工具 | VisualSVN Server | 关闭
  3. VMware Workstation: 开始 | VMware Workstation | 编辑 | 首选项 | 共享虚拟机 | 禁用共享
  4. HP LoadRunner: 右侧任务栏 | 右键 | 关闭
  5. 修改XAMPP Apache 端口:Config | httpd.conf修改Linsten 80 | Httpd-ssl.conf修改 Listen 443
  • 无法启动MySQL:请认真查看错误日志,找到已经启动的MySQL的程序进程,杀掉该进程。

使用unittest编写测试脚本

通过上面的例子,我们可以简单的写出Selenium WebDriver的脚本,但是对于测试工作来说,上述的脚本还远远不够。因为上述的脚本没有“检查”。

接下来我们将会使用Python语言的unittest框架展开“检查”。

unittest基础

unittest框架的原本的名字是PyUnit。是从JUnit这样一个被广泛使用的Java应用开发的单元测试框架创造而来。类似的框架还有NUnit(.Net开发的单元测试框架)等。

我们可以使用unittest框架为任意Python项目编写可理解的单元测试集合。现在这个unittest已经作为Python的标准库模块发布。我们安装完Python以后,便可以直接使用unittest。

unittest框架提供了编写test casestest suitestest fixtures的基本功能。我们首先关注 Test cases的编写与执行。

使用unittest需要以下简单的三步:

  • 引入unittest模组
  • 继承unittest.TestCase基类
  • 测试方法以test开头

unittest示例

## 引入unittest模组
import unittest

## 定义测试类,名字为DemoTests
## 该类必须继承unittest.TestCase基类
class DemoTests(unittest.TestCase):

    ## 使用'@'修饰符,注明该方法是类的方法
    ## setUpClass方法是在执行测试之前需要先调用的方法
    ## 是开始测试前的初始化工作
    @classmethod
    def setUpClass(cls):
        print("call setUpClass()")
    
    ## 每一个测试开始前的预置条件
    def setUp(self):
        print("call setUp()")
        
    ## 每一个测试结束以后的清理工作
    def tearDown(self):
        print("call tearDown()")

    ## 测试一(务必以test开头)
    def test_01(self):
        print("call test_01()")
        pass

    ## 测试三(务必以test开头)
    def test_02(self):
        print("call test_02()")
        pass

    ## 测试三(务必以test开头)
    def test_03(self):
        print("call test_03()")
        pass

    ## tearDownClass方法是执行完所有测试后调用的方法
    ## 是测试结束后的清除工作
    @classmethod
    def tearDownClass(cls):
        print("call tearDownClass()")

# 执行测试主函数
if __name__ == '__main__':
    ## 执行main全局方法,将会执行上述所有以test开头的测试方法
    unittest.main(verbosity=2)
需要注意步骤:
    1. 引入 unittest 模组
    2. 继承 unittest.TestCase 类
    3. 做测试用例的方法,方法以 test_ 开头
    * 4. 附加 setUp(), tearDown(), 在每个 test_ 方法执行前后 进行执行
    * 5. 附加 setUpClass(), tearDownClass()
        需要在 类实例化的对象,运行的开头和结尾进行执行。
    加了星号(*)的步骤,可以不用。

上述代码的运行结果:

call setUpClass()
call setUp()
call test_01()
call tearDown()
call setUp()
call test_02()
call tearDown()
call setUp()
call test_06()
call tearDown()
call tearDownClass()

Python知识的补充:

  1. Python文件的后缀名是.py
  2. .py文件可以用来直接执行。也可以被用来作为模块导入。在cmd命令行中执行的命令为python demo.py
  3. 在Python中导入模块(模组)一般使用的是import

理解unittest断言

方法 Method 检查条件
assertEqual(a, b [, msg]) a == b,msg可选,用来解释失败的原因
assertNotEqual(a, b [, msg] a != b,msg可选,用来解释失败的原因
assertTrue(x [, msg]) x 是真,msg可选,用来解释失败的原因
assertFalse(x [, msg]) x 是假,msg可选,用来解释失败的原因
assertIsNot(a, b [, msg]) a 不是 b,msg可选,用来解释失败的原因

编写WebDriver测试脚本

接下来我们查看一个完整的Selenium WebDriver自动化测试实例

在上述部分的代码中,有禅道的示例,改为由unittest框架驱动运行

from time import sleep
import unittest
from selenium import webdriver

__author__ = 'Administrator'


class ZentaoTestByUnittest(unittest.TestCase):
    def setUp(self):
        ## 设定一个base url,存储根目录的地址
        self.base_url = "http://172.31.95.220/zentaopms/www"

        ## 实例化火狐浏览器的对象
        self.driver = webdriver.Firefox()

    def tearDown(self):
        ## 退出火狐浏览器
        self.driver.quit()

    def test_login(self):
        driver = self.driver

        ## 用get的方式,打开base url
        driver.get(self.base_url)

        ## 让python休息2秒钟,给火狐2秒时间加载页面
        sleep(2)

        ## 查找登录页面的用户输入框,并把元素保存到account中
        account = driver.find_element_by_id("account")

        ## 清除 account 已经输入的字符,并输入 admin
        account.clear()
        account.send_keys("admin")

        ## 查找登录页面的密码输入框,并把元素保存到 password 中
        password = driver.find_element_by_name("password")

        ## 清除 password 已经输入的字符,并输入 123456
        password.clear()
        password.send_keys("123456")

        ## 查找 保持登录 的元素(复选框),并打勾
        driver.find_element_by_id("keepLoginon").click()

        ## 查找 登录 的元素,点击登录
        driver.find_element_by_id("submit").click()

        ## 让python休息5秒钟,给火狐5秒时间加载页面
        sleep(5)

        ## 做验证
        ## 设定期望的结果
        expected = self.base_url + "/index.php?m=my&f=989indes"

        ## 获取实际的结果
        actual = driver.current_url

        self.assertEqual(expected, actual, "系统登录跳转主页失败!")



## 主方法的入口
if __name__ == "__main__":
    ## 实例化一个ZentaoTest对象,调用它登录的方法
    unittest.main()

以及 然之系统添加了unittest的运行代码

import unittest
from time import sleep

from selenium import webdriver


class RanzhiTestAdvanced(unittest.TestCase):

    def setUp(self):
        ## 声明一个变量,用来存Base URL,可以拼接成其他地址
        self.base_url = "http://172.31.95.220/ranzhi/www"

        ## 声明一个变量,用来存Firefox()的实例化对象
        self.driver = webdriver.Firefox()

    def tearDown(self):
        self.driver.quit()

    def test_login_with_english(self):
        driver = self.driver
        base_url = self.base_url

        ## 用driver打开网页,登录页面
        driver.get(base_url)

        sleep(2)
        ## 点击 语言切换的按钮
        driver.find_element_by_class_name("btn").click()

        sleep(1)
        ## 选择 语言 English
        driver.find_element_by_link_text("English").click()

        sleep(5)
        expected_lang = "English"

        actual_lang = driver.find_element_by_class_name("btn").text

        ## 检查 是否切换语言成功
        self.assertEqual(expected_lang, actual_lang, "系统语言切换英语失败!")

        #sleep(100)
        ## 查找“输入用户”的输入框,
        ## 并且清除已经存在的输入数据,重新输入用户“admin”
        driver.find_element_by_id("account").clear()
        driver.find_element_by_id("account").send_keys("admin")

        ## 查找“输入密码”的输入框,
        ## 并且清除已经存在的输入数据,重新输入密码“123456”
        driver.find_element_by_id("password").clear()
        driver.find_element_by_id("password").send_keys("123456")

        ## 勾选 保持登录 复选框
        driver.find_element_by_id("keepLogin1").click()

        ## 查找登录的按钮,点击登录
        driver.find_element_by_id("submit").click()
        sleep(5)

        ## 做验证
        expected_url_after_login = base_url + "/sys/index.php?m=index&f=index"
        actual_url_after_login = driver.current_url

        self.assertEqual(expected_url_after_login,
                         actual_url_after_login,
                         "系统登录跳转失败!")

        ## 点击 头像按钮
        driver.find_element_by_id("start").click()
        sleep(1)

        ## 点击 退出
        driver.find_element_by_link_text("Logout").click()

        ## 做验证
        expected_url_after_logout = base_url + "/sys/index.php?m=user&f=login"
        actual_url_after_logout = driver.current_url

        self.assertEqual(expected_url_after_logout,
                         actual_url_after_logout,
                         "系统登录跳转失败!")

if __name__ == "__main__":
    unittest.main()

使用TestNG编写测试

在上述环境搭建好以后,我们便可使用JUnit来编写自动化脚本程序,执行Selenium自动化测试。

通过上面的例子,我们可以简单的写出Selenium WebDriver的脚本,但是对于测试工作来说,上述的脚本还远远不够。因为上述的脚本没有“检查”。

接下来我们将会使用Java语言的TestNG框架展开“检查”。

TestNG为我们在项目测试中常用到的单元测试框架,很多程序员的理想套件,本篇文章主要介绍TestNG的常见annotation.

初始化标注

TestNG提供了@BeforeTest和@AfterTest,在每个测试函数调用之前/后都会调用。

@BeforeTest: Method annotated with @BeforeTest executes before every test.
@AfterTest: Method annotated with @AfterTest executes after every test.

如果在测试之前有些工作我们只想做一次,用不着每个函数之前都做一次。比如读一个很大的文件。那就用下面两个来标注:
@BeforeClass
@AfterClass

注意:
@BeforeTest/@AfterTest可以有多个; @BeforeClass/@AfterClass 只有一个

TestNG框架图

TestNG单元测试框架示意图.png

TestNG示例

package example1;
 
import org.testng.annotations.*;
 
public class SimpleTest {
 
 @BeforeClass
 public void setUp() {
   // code that will be invoked when this test is instantiated
 }
 
 @Test(groups = { "fast" })
 public void aFastTest() {
   System.out.println("Fast test");
   Assert.assertEqual
 }
 
 @Test(groups = { "slow" })
 public void aSlowTest() {
    System.out.println("Slow test");
 }
 
}
  • TestNG断言
方法 Method 检查条件
assertEquals(a, b [, msg]) a == b,msg可选,用来解释失败的原因
assertNotEquals(a, b [, msg] a != b,msg可选,用来解释失败的原因
assertTrue(x [, msg]) x 是真,msg可选,用来解释失败的原因
assertFalse(x [, msg]) x 是假,msg可选,用来解释失败的原因
assertIsNot(a, b [, msg]) a 不是 b,msg可选,用来解释失败的原因
assertNull(x[, msg]) x 是null,msg可选,用来解释失败的原因
assertNotNull(x[, msg]) x 不是null,msg可选,用来解释失败的原因

在IDEA中使用Git集成操作

Git 环境的搭建

可以访问https://coding.net/u/lintyleo/p/WeekendSelenium/git,查看自动化测试代码。

  1. 在windows系统中安装Git-2.x.1-32-bit.exe或者Git-2.x.1-64-bit.exe,根据电脑系统为32位或者64位选择正确的对应的git版本。安装包可以在git官网上下载 https://git-scm.com

  2. 在Windows系统中安装TortoiseGit,同样需要根据系统为32位和64位进行选择安装。

  3. 安装完毕以后,在非系统盘创建'Git'文件夹【这条是建议】

  4. 在上一步创建的文件夹中,右键鼠标,选择'Git clone',里面填写 git 项目的路径。例如在Coding.net 或者 Github.com 网站中的项目地址。“https://git.coding.net/lintyleo/WeekendSelenium.git

    Snap1.jpg
    Snap2.jpg

    至此,代码都已经被下载了。如果你需要更新,在文件夹中,右键 | Git Sync,选择 Pull

    Snap12.jpg
  5. 此后,请务必在刚才克隆后的文件夹中,进行操作,便可以在IDEA中集成Git操作。

    把要添加的Java 和 Python 项目的根目录直接复制到刚刚克隆的文件夹中

    Snap3.jpg

  6. 用IDEA创建新的项目,或者打开老的项目,这些项目必须存放在上一步克隆的地址中,方可进行操作。

    Snap4.jpg

    PyCharm也是一样

    Snap5.jpg
  7. 如果IDEA中没有发现Git的菜单,请选择 VCS | Enable VCS 菜单进行激活Git。然后再尝试。

    Snap7.jpg
  8. 选择VCS | Git | add

    Snap8.jpg
  9. 选择VCS | Commit Changes

    Snap11.jpg

WebDriver API 基本操作

这里我们将会开始WebDriver API的基本操作,从元素定位以及浏览器的基本操作开始。

定位符

元素的定位和操作是自动化测试的核心部分,其操作是建立在定位的基础上的。因此我们首选要开始定位元素。

在html里面,元素具有各种各样的属性。我们可以通过这样唯一区别其他元素的属性来定位到这个元素。WebDriver提供了一系列的元素定位方法。常见的有以下几种:

  • id
  • name
  • class name
  • tag
  • link text
  • partial link text
  • xpath
  • css selector

查找简单元素

我们从简单的一个元素开始定位。最基本的方法是idname。大多数元素有这两个属性,在对控件的idname命名是一般也会使其有意义,而取不同的名字。

例如我们看下面这段html

<input id="search" type="text" name="q" value="" class="input-text" maxlength="128" />

我们可以使用对应的方法来定位这个input

findElement(By.id("search"))
findElement((By.name("q"))
findElement((By.className("input-text"))

这里我们开始用最简单的方式来尝试定位

查看下面一个例子

driver.get("http://pro.demo.zentao.net")
// 用name定位用户文本输入框
WebElement accountField = driver.findElement(By.name("account"))
// 用name定位密码文本输入框
WebElement passwordField = self.driver.findElement(By.name("password"))
accountField.clear()
passwordField.clear()
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

// 输入用户名demo
accountField.sendKeys("demo")
// 输入密码123456
passwordField.sendKeys("123456")
driver.findElement("submit").click()
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

WebElement companyname = driver.findElement(By.id("companyname"))
assertEquals("标题验证","demo项目管理系统", companyname.text)

示例2

driver.findElement(By.id(("menuproduct")).click()
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

driver.findElement(By.id(("menuproject")).click()
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

driver.findElement(By.id(("menuqa")).click()
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

driver.findElement(By.id(("menudoc")).click()
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

driver.findElement(By.id(("menureport")).click()
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

driver.findElement(By.id(("menucompany")).click()
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

driver.findElement(By.linkText(("退出")).click()
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

此外XPath定位和CSS Selector定位,和定位一组元素这样的内容案例,将在后续的讲义继续探讨和讲解。

控制浏览器

浏览器的控制也是自动化测试的一个基本组成部分,我们可以将浏览器最大化,设置浏览器的高度和宽度以及对浏览器进行导航操作等。

// 浏览器最大化
driver.manage().window().maximize();

// 设置浏览器的高度为800像素,宽度为480像素
driver.manage().window().setSize(new Dimension(800, 600))
  
// 隐式等待
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

// 浏览器后退
driver.navigate().back();

// 浏览器前进
driver.navigate().forward()

使用CSS选择器

CSS是一种设计师用来描绘HTML文档的视觉的层叠样式表。一般来说CSS用来定位多种多样的风格,同时可以用来是同样的标签使用同样的风格等。类似于XPath,Selenium2也可以使用CSS选择器来定位元素。

使用开发者工具配合,可以找到CSS选择器。

编程基础

面向对象的概念

类: RanzhiCommon
业务的模板
纸上谈兵
做设计
对象: new RanzhiCommon()
把设计转换为实体:构造 new 和 RanzhiCommon()
实例化
实体=对象
对象就可以被调用做事情

如果需要把另一个东西放到新实例化出来的对象中,需要在构造过程加入

构造方法:
方法名:类名()

  • Java语言

    • 类的创建

      // 类名:大骆驼
      // 类名:名词
      class RanzhiCommon{
        // 1. 全局变量
        // 在本个类里面的所有地方都可以用的变量
        WebDriver baseDriver = null;
        // ...
        
        // 2. 构造方法
        // 当实例化本类的时候,调用的方法。做出自己
        // 构造方法可以传参数,也可以不传
        public RanzhiCommon(WebDriver driver, String url){
          // 用全局的变量来接住传进来的值
          this.baseDriver = driver;
          // ...
        }
        
        // 3. 成员方法
        // 可以有返回值,也可以无返回值
        // void: 无返回值
        // 有返回值的,都需要用 return
        // boolean: 布尔型,返回 true, false
        // int: 整型,返回一个数字
        // String: 字符串型,返回一个字符串
        // 当本类被实例化成一个具体的对象的时候,就可以调用这些成员方法
        public void logIn(String account, String password){
          // ...
        }
        
        // 有返回值的方法
        // 调用该方法,就可以用变量来接住返回值。
        // 变量的类型必须和返回值类型一致
        public String changeLanguage(String lang){
          // ...
          String displayText = ...;
          return displayText;
            
        }
        
      }
      
    • 类的实例化

      // new 是实例化的关键字
      // new 后面的方法,其实就是 构造方法。
      // 被实例化的类的构造方法:RanzhiCommon这个类的构造方法
      RanzhiCommmon common = new RanzhiCommon(this.baseDriver, this.baseUrl);
      
      // 然后,就可以被调用了
      common.logIn("admin", "password");
      String actualDisplayText = common.changeLanguage("en");
      
    • if 语句

      // 判断真假
      // 如果被判断的变量是个 布尔型的,boolean型的,就不建议写 isFirstLine == true
      if (isFirstLine){
        // ...
      }
      
      if (isFirstLine){
        // ...
      }
      else{
        // ...
      }
        
      
    • continue 和 break

      分支语句的中断

      • continue,只是中断当前的循环

      • break,中断所有的循环

        用于分支语句:比如循环,判断等。
        以谈恋爱为例子
        for(每一天){

        if 吵架{
          continue;
        }
        看电影
        吃饭
        

        }
        continue:当天冷战,明天继续

        for(每一天){

        if 吵架{
          break;
        }
        看电影
        吃饭
        

        }
        break: 分手,明天没有了。。。

    • switch 语句

      主要用于多语言的判断,做为共同的入口管理

      Python没有switch语句

      String langNumber = "";
      switch (lang) {
        case "en":
          langNumber = "3";
          break;
        case "zh_CN":
          langNumber = "1";
          break;
        case "zh_TW":
          langNumber = "2";
          break;
      }
      

      python只能用if语句来处理,当然Java也可以用if语句来代替。

      if lang == "en":
          lang_number = 3
      elif lang == "zh_CN":
          lang_number = 1
      elif lang == "zh_TW":
          lang_number = 2
      else:
          return "Error lang_number"
      
    • foreach 语句

      把被循环的数据,一个个循环一遍。一个一个循环

       for (CSVRecord row : csvData) {
         // ...
       }
      

      被循环的数据,就是csvData,csvData中每一条记录,都是一个CSVRecord。一个个循环,就得到一个个row。

  • Python语言

    • 不同之处

      • 没有花括号{},Python靠对齐方式来代替。

      • 变量声明的时候,不需要指明类型

      • 类实例化的时候,不用 new

        common = RanzhiCommon(self.firefox_driver, self.base_url)
        

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容