|
5#
楼主 |
发表于 2018-5-4 16:15:57
|
只看该作者
# 输入空格键+“教程”
driver.find_element_by_id("kw").send_keys(Keys.SPACE)
driver.find_element_by_id("kw").send_keys("教程")
time.sleep(3)
# ctrl+a 全选输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')
1.4.5 截图操作
截图的方法:save_screenshot(file)
1.5 unittest 单元测试框
在上一节,我们对 Selenium WebDriver 的使用,仅仅停留在让网页自动的进行操作的阶段,并没有对任何一个
步骤进行“检查”。当然,这样没有“检查”的操作,实际上是没有测试意义的。那么第一项,我们需要解决的便是
“检查”的问题。
所谓“检查”,实际上就是断言。对需要检查的步骤操作,通过对预先设置的期望值,和执行结果的实际值之间的
对比,得到测试的结果。在这里,我们并不需要单独的写 if 语句进行各种判定,而是可以使用编程语言中对应的
单元测试框架,即可解决好此类问题。
目前 Java 语言主流的单元测试框架有 JUnit 和 TestNG。Python 语言主流的单元测试框架有 unittest 。本小节的
内容,主要介绍 unittest 的使用,探讨单元测试框架如何帮助自动化测试。
接下来我们将会使用 Python 语言的unittest框架展开“检查”。unittest框架的原本的名字是PyUnit。是从JUnit 这样
一个被广泛使用的 经典的Java应用开发的单元测试框架创造而来。类似的框架还有NUnit(.Net开发的单元测试
框架)等。我们可以使用unittest框架为任意Python项目编写可理解的单元测试集合。现在这个unittest已经作为
Python的标准库模块发布。我们安装完Python以后,便可以直接使用unittest。
使用unittest需要以下简单的三步:
引入unittest模组
继承unittest.TestCase基类
测试方法以test开头
unittest 并未使用 Java 语言常见的注解方式,依旧停留在 比较早期的 Java 版本中依靠方法名称进行识别的方
式。主要有以下两个固定名字的方法:
setUp():在每个测试方法运行前,执行。是测试前置条件。
tearDown():在每个测试方法运行后执行,是测试清理操作。
具体的代码如下:
## 引入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)
需要注意步骤:
引入 unittest 模组
继承 unittest.TestCase 类
做测试用例的方法,方法以 test_ 开头
附加 setUp(), tearDown(), 在每个 test_ 方法执行前后 进行执行
附加 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()
为什么选择 unittest
清晰的单元测试框架,提供 TestCase, TestSuite, TextTestRunner 等基本类
unittest 是 原生 Python 的一部分
unittest 有第三方可用的 HTML 库,可以轻松的生成 测试报告
unittest 的断言配置使用
unittest 的断言,属于 TestCase类,只要继承了该类,均可以通过 self调用断言
方法 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可选,用来解释失败的原因
1.6 为什么需要封装 Selenium
什么是封装
封装是一个面向对象编程的概念,是面向对象编程的核心属性,通过将代码内部实现进行密封和包装,从而简
化编程。对Selenium进行封装的好处主要有如下三个方面:
使用成本低
不需要要求所有的测试工程师会熟练使用Selenium,而只需要会使用封装以后的代码
不需要对所有的测试工程师进行完整培训。也避免工作交接的成本。
测试人员使用统一的代码库
维护成本低
通过封装,在代码发生大范围变化和迁移的时候,不需要维护所有代码,只需要变更封装的部分即可
维护代码不需要有大量的工程师,只需要有核心的工程师进行封装的维护即可
代码安全性
对作为第三方的Selenium进行封装,是代码安全的基础。
对于任何的代码的安全隐患,必须由封装来解决,使得风险可控。
使用者并不知道封装内部的代码结构。
1.7 封装的概念与基本操作
关键方法的封装思路
封装的具体示例:
找到一个指定输入框(selector),并且输入指定的字符(text)
type(selector, text)
不用在业务逻辑中,使用多次的 find_element_by_id(...))
def type(self, selector, text):
"""
Operation input box.
Usage:
driver.type("i,el","selenium")
"""
el = self._locate_element(selector)
el.clear()
el.send_keys(text)
找到一个可以点击的元素(selector),并且点击(click)
click(selector)
def click(self, selector):
"""
It can click any text / image can be clicked
Connection, check box, radio buttons, and even drop-down box etc..
Usage:
driver.click("i,el")
"""
el = self._locate_element(selector)
el.click()
找到一个指定的frame,并且切换进去
switch_to_frame(selector)
def switch_to_frame(self, selector):
"""
Switch to the specified frame.
Usage:
driver.switch_to_frame("i,el")
"""
el = self._locate_element(selector)
self.base_driver.switch_to.frame(el)
找到一个指定的select,并且通过index进行选择
select_by_index(selector, index)
def select_by_index(self, selector, index):
"""
It can click any text / image can be clicked
Connection, check box, radio buttons, and even drop-down box etc..
Usage:
driver.select_by_index("i,el")
"""
el = self._locate_element(selector)
Select(el).select_by_index(index)
以上的代码是封装了_locate_element()的几种方法,在具体使用封装过的代码的时候,只需要简单的调用即可。
接下来的重点,是介绍 _locate_element(selector)的封装方式。
查找元素:find_element_by_...)
支持各种的查找:8种方式都需要支持,必须通过 selector 显示出分类
selector中需要包含一个特殊符号
实例化 封装好的类的时候,需要约定好是什么特殊符号
强制性用硬编码 hard code来实例化,例如 , 或者 ? 或者 其他非常用字符 =>
或者,构造方法中,传递 this.byChar
要把查找到元素的返回给调用的地方:必须要有返回值,类型是 WebElement
def _locate_element(self, selector):
"""
to locate element by selector
:arg
selector should be passed by an example with "i,xxx"
"x,//*[@id='langs']/button"
:returns
DOM element
"""
if self.by_char not in selector:
return self.base_driver.find_element_by_id(selector)
selector_by = selector.split(self.by_char)[0].strip()
selector_value = selector.split(self.by_char)[1].strip()
if selector_by == "i" or selector_by == 'id':
element = self.base_driver.find_element_by_id(selector_value)
elif selector_by == "n" or selector_by == 'name':
element = self.base_driver.find_element_by_name(selector_value)
elif selector_by == "c" or selector_by == 'class_name':
element = self.base_driver.find_element_by_class_name(selector_value)
elif selector_by == "l" or selector_by == 'link_text':
element = self.base_driver.find_element_by_link_text(selector_value)
elif selector_by == "p" or selector_by == 'partial_link_text':
element = self.base_driver.find_element_by_partial_link_text(selector_value)
elif selector_by == "t" or selector_by == 'tag_name':
element = self.base_driver.find_element_by_tag_name(selector_value)
elif selector_by == "x" or selector_by == 'xpath':
element = self.base_driver.find_element_by_xpath(selector_value)
elif selector_by == "s" or selector_by == 'css_selector':
element = self.base_driver.find_element_by_css_selector(selector_value)
else:
raise NameError("Please enter a valid type of targeting elements.")
|
|