前情介绍:
在自动化测试框架中,数据驱动的意思是指定的是测试用例或者说测试套件是由外部数据集合来驱动的框架。
数据集合(也可称之为数据来源)可以是任何类型的数据文件比如xls,xlsx,csv等等,甚至可以是数据库中的表。总之,是一个放数据的地方就对了。
核心思想就是数据和测试代码分离,及时当测试数据发生大量变化的情况下测试代码(或者说测试用例)可以保持不变。
最常见的例子是需要用多个不同的账号和密码来登陆某个邮箱,来验证哪些是有效的值,哪些是错误的值,或者哪些值可以导致出错等等。
数据驱动并不是和关键字驱动等水火不相容的一种驱动模式,我的理解是,两者更像是互相协助的关系。甚至你把数据看成一种关键字也未尝不可。
练习环境配置
实例1(UI自动化-百度搜索)
实例2(有效登录)
实例3(无效登录)
实例4 (Appium)
实例5 (连接mysql数据库)
实例6 (GET/POST请求)
实例7(接口API测试)
Appium Error总结
robotframework Error总结
测试需求:
为了更纯粹一点的看到RF中的数据驱动的模式,这次采用了官方的Demo做一个讲解。
对 一个 简单计算器的Calculator.py进行测试,Calculator.py的代码如下(写的漂亮):
class Calculator(object):
BUTTONS = '1234567890+-*/C='
def __init__(self):
self._expression = ''
def push(self, button):
if button not in self.BUTTONS:
raise CalculationError("Invalid button '%s'." % button)
if button == '=':
self._expression = self._calculate(self._expression)
elif button == 'C':
self._expression = ''
elif button == '/':
self._expression += '//' # Integer division also in Python 3
else:
self._expression += button
return self._expression
def _calculate(self, expression):
try:
return str(eval(expression))
except SyntaxError:
raise CalculationError('Invalid expression.')
except ZeroDivisionError:
raise CalculationError('Division by zero.')
class CalculationError(Exception):
pass
测试设计:
数据驱动引入了一个非常有效的概念,即“模板”概念,在很多测试场景下,测试人员输入的操作是有一定重复性的,区别只在于输入的数据,还是以登陆为例,除了包含正常的测试用例,还需要有其他的异常用例覆盖才能保证登陆接口的正确性。基于横向构造不同的测试数据输入来判断不同的测试结果,即为数据驱动。行为可以封装成模板。
先用一个CalculatorLibrary库来进行封装需要做的测试步骤,对应的验证和错误处理
- push button
- push buttons
- result_should_be
- should_cause_error
再在RF中设计两个模板来使用上面库中的方法。
不同的输入数据则在测试用例中体现。
测试实现:
1 . 编写CalculatorLibrary.py文件,代码示例如下(最漂亮的还是写注释的地方,啧啧啧):
from calculator import Calculator, CalculationError
class CalculatorLibrary(object):
"""Test library for testing *Calculator* business logic.
Interacts with the calculator directly using its ``push`` method.
"""
def __init__(self):
self._calc = Calculator()
self._result = ''
def push_button(self, button):
"""Pushes the specified ``button``.
The given value is passed to the calculator directly. Valid buttons
are everything that the calculator accepts.
Examples:
| Push Button | 1 |
| Push Button | C |
Use `Push Buttons` if you need to input longer expressions.
"""
self._result = self._calc.push(button)
def push_buttons(self, buttons):
"""Pushes the specified ``buttons``.
Uses `Push Button` to push all the buttons that must be given as
a single string. Possible spaces are ignored.
Example:
| Push Buttons | 1 + 2 = |
"""
for button in buttons.replace(' ', ''):
self.push_button(button)
def result_should_be(self, expected):
"""Verifies that the current result is ``expected``.
Example:
| Push Buttons | 1 + 2 = |
| Result Should Be | 3 |
"""
if self._result != expected:
raise AssertionError('%s != %s' % (self._result, expected))
def should_cause_error(self, expression):
"""Verifies that calculating the given ``expression`` causes an error.
The error message is returned and can be verified using, for example,
`Should Be Equal` or other keywords in `BuiltIn` library.
Examples:
| Should Cause Error | invalid | |
| ${error} = | Should Cause Error | 1 / 0 |
| Should Be Equal | ${error} | Division by zero. |
"""
try:
self.push_buttons(expression)
except CalculationError as err:
return str(err)
else:
raise AssertionError("'%s' should have caused an error."
% expression)
2 . RF中创建一个Data Driven的项目,测试用例和模板的名字的结构如下:
在项目那一级导入CalculatorLibrary库,导入后CalculatorLibrary里的方法都可以被作为关键字使用。
- 将刚才的CalculatorLibrary.py文件放在和这个项目同一个目录下。
- 点击Library按钮后输入文件名即可导入。
3 . 最下方的两个齿轮形状的就是模板形式,可以通过New User Keyword的方式来创建(创建好一个项目后,在项目名上右键则可创建User Keyword),对于计算器测试来说,也就两种结果,一种是输入正常的值得到正常的结果,一种是输入异常的值得到错误提示
Calculator - 正常的值的测试步骤
Calculator should fail-异常的值的测试步骤
4 .构造测试用例来进行测试。
加减乘除,输入异常,输入不允许的值(一串字符串,空值,除以0),比如:
最终代码如下:
*** Settings ***
Documentation Example test cases using the data-driven testing approach.
...
... The _data-driven_ style works well when you need to repeat
... the same workflow multiple times.
...
... Tests use ``Calculate`` keyword created in this file, that in
... turn uses keywords in ``CalculatorLibrary.py``. An exception
... is the last test that has a custom _template keyword_.
...
... Notice that one of these tests fails on purpose to show how
... failures look like.
Test Template Calculate
Library CalculatorLibrary.py
*** Test Cases *** Expression Expected
Addition 12 + 2 + 2 16
2 + -3 -1
Subtraction 12 - 2 - 2 8
2 - -3 5
Multiplication 12 * 2 * 2 48
2 * -3 -6
Division 12 / 2 / 2 3
2 / -3 -1
Failing 1 + 1 3
Calculation error [Template] Calculation should fail
kekkonen Invalid button 'k'.
${EMPTY} Invalid expression.
1 / 0 Division by zero.
*** Keywords ***
Calculate
[Arguments] ${expression} ${expected}
Push buttons C${expression}=
Result should be ${expected}
Calculation should fail
[Arguments] ${expression} ${expected}
${error} = Should cause error C${expression}=
Should be equal ${expected} ${error} # Using `BuiltIn` keyword
CC先生说:RF的数据驱动看起来的确是非常简洁的,采用了封装的思维,将更多的操作都封装到库,模板中,干净利落的实现了测试数据和测试步骤的分离。大热天的,看起来还真是清爽~~~