RobotFramework官方demo Quick Start Guide浅析
by:授客 QQ:1033553122
博客:http://blog.sina.com.cn/ishouke
欢迎加入软件性能测试交流QQ群:7156436
目录
1、 开发环境 1
2、 安装robotframework 1
3、 脚本分析 2
sut/login.py 2
Lib/LoginLibrary.py 6
运行rst配置文件 9
1、 开发环境
win7 x64
PyCharm 4.0.5
Python 3.3.2
robotframework-master.zip
下载地址1:https://github.com/robotframework/robotframework
下载地址2:http://pan.baidu.com/s/1dE2nz9Z
QuickStartGuide-master.zip
下载地址1:https://github.com/robotframework/QuickStartGuide
下载地址2:http://pan.baidu.com/s/1gfiMS5l
(因为官方的demo有些bug,在其基础上做了些修改)
2、 安装robotframework
下载.zip压缩文件后解压安装
D:\Program Files\python33\Lib\site-packages>robotframework-master>python setup.py
修改path环境变量,增加指向robot的路径
D:\Program Files\python33\Scripts
参考连接:https://github.com/robotframework/robotframework/blob/master/INSTALL.rst
3、 脚本分析
sut/login.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from __future__ import print_function
import os.path
import sys
import tempfile
import study
DATABASE_FILE = os.path.join(tempfile.gettempdir(), 'robotframework-quickstart-db.txt')
class User(object):
def __init__(self, username, password, status='Inactive'):
self._validate_password(password)
self._username = username
self._password = password
self._status = status
@property
def username(self):
return self._username
@username.setter
def username(self, username):
self._username = username
@property
def password(self):
return self._password
@password.setter
def password(self, password):
self._validate_password(password)
self._password = password
@property
def status(self):
return self._status
@status.setter
def status(self, status):
self._status = status
def _validate_password(self, password):
if not (7 <= len(password) <= 12):
raise ValueError('Password must be 7~12 characters long')
if not self._validate_password_chars(password):
raise ValueError('Password must be a combiantion of lowercase and'
'uppercase letters and numbers')
def _validate_password_chars(self, password):
has_lower = has_upper = has_number = False
for char in password:
if char.islower():
has_lower = True
elif char.isupper():
has_upper = True
elif char.isdigit():
has_number = True
else:
return False
return has_lower and has_upper and has_number
class UserDataBase(object):
def __init__(self, db_file=DATABASE_FILE):
self.users = self._read_users(db_file)
self.db_file = db_file
def _read_users(self, path):
users = {}
if os.path.isfile(path): #判断所给路径path是否指向一个文件
with open(path) as file:
for row in file.readlines():
user = User(*row.rstrip('\r\n').split('\t'))
users[user.username] = user
return users
def create_user(self, username, password):
try:
user = User(username, password)
except ValueError as err:
return 'Creating user failed: %s' % err
self.users[user.username] = user
return 'SUCCESS'
def login(self, username, password):
if self._is_valid_user(username, password):
self.users[username].status = 'Active'
return 'Logged In'
return 'Access Denied'
def _is_valid_user(self, username, password):
return (username in self.users and self.users[username].password == password)
def change_password(self, username, old_pwd, new_pwd):
try:
if not self._is_valid_user(username, old_pwd):
raise ValueError('Access Denied')
self.users[username].password = new_pwd
except ValueError as err:
return 'Changing password faild:%s' % err
else:
return 'SUCCESS'
def save(self):
with open(self.db_file, 'w') as file:
for user in self.users.values():
file.write('%s\t%s\t%s\n' % (user.username, user.password, user.status))
def truncate(self):
with open(self.db_file, 'w') as file:
file.truncate()
return 'SUCCESS'
def __enter__(self):
return self
def __exit__(self, *exec_info):
self.save()
def login(username, password):
with UserDataBase() as db:
print(db.login(username, password))
def create_user(username, password):
with UserDataBase() as db:
print(db.create_user(username, password))
def change_password(username, old_pwd, new_pwd):
with UserDataBase() as db:
print(db.change_password(username, old_pwd, new_pwd))
def truncate():
with UserDataBase() as db:
print(db.truncate())
def help():
print('Usage: %s { create | login | change-password | truncate | help}' % os.path.basename(sys.argv[0]))
if __name__ == '__main__':
actions = {'create': create_user, 'login': login, 'change-password': change_password, 'truncatefile': truncate, 'help': help}
try:
study.testt()
action = sys.argv[1]
except IndexError:
action = 'help'
args = sys.argv[2:]
try:
actions[action](*args)
except (KeyError, TypeError):
help()
运行脚本:
1)登录用户帐号不存在、密码错误
E:\Projects\studyproject>python sut/login.py login nobody P4ssw0rd
Access Denied
2)创建用户账户
E:\Projects\studyproject>python sut/login.py create fred P4ssw0rd
SUCCESS
3)用创建的用户登录
E:\Projects\studyproject>python sut/login.py login fred P4ssw0rd
Logged In
4)创建用户时,用户密码必须包含7-12字符
E:\Projects\studyproject>python sut/login.py create fred short
Creating user failed: Password must be 7~12 characters long
5)创建用户时,用户密码必须包含大小写字母和数字字符
E:\Projects\studyproject>python sut/login.py create fred invalid
Creating user failed: Password must be a combiantion of lowercase anduppercase l
etters and numbers
6)修改用户密码,提供错误的原始密码
E:\Projects\studyproject>python sut/login.py change-password fred wrong NewP4ss
Changing password faild:Access Denied
7)修改用户密码,提供正确的原始密码
E:\Projects\studyproject>python sut/login.py change-password fred P4ssw0rd NewP4ss
SUCCESS
Lib/LoginLibrary.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import os.path
import subprocess
import sys
class LoginLibrary(object):
def __init__(self):
self._sut_path = os.path.join(os.path.dirname(__file__),
'..', 'sut', 'login.py')
self._status = ''
def create_user(self, username, password):
self._run_command('create', username, password)
def change_password(self, username, old_pwd, new_pwd):
self._run_command('change-password', username, old_pwd, new_pwd)
def attempt_to_login_with_credentials(self, username, password):
self._run_command('login', username, password)
def login(self, username, password):
self._run_command('login', username, password)
def status_should_be(self, expected_status):
if expected_status != self._status:
raise AssertionError("Expected status to be '%s' but was '%s'."
% (expected_status, self._status))
def truncate(self):
self._run_command('truncatefile')
def _run_command(self, command, *args):
command = [sys.executable, self._sut_path, command] + list(args)
process = subprocess.Popen(command, universal_newlines=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
self._status = process.communicate()[0].strip()
QuickStart.rst文件
.. code:: robotframework
*** Test Cases ***
User can create an account and log in
[Tags] mytag
Create Valid User fred P4ssw0rd
Attempt to Login with Credentials fred P4ssw0rd
Status Should Be Logged In
Invalid password
[Template] Creating user with invalid password should fail
abCD5 ${PWD INVALID LENGTH}
abCD567890123 ${PWD INVALID LENGTH}
123DEFG ${PWD INVALID CONTENT}
abcd56789 ${PWD INVALID CONTENT}
AbCdEfGh ${PWD INVALID CONTENT}
abCD56+ ${PWD INVALID CONTENT}
User can change password
Given A user has a valid account
When she changes her password
Then she can log in with the new password
And she cannot use the old password anymore
*** Keywords ***
Create valid user
[Arguments] ${username} ${password}
Create user ${username} ${password}
Status should be SUCCESS
Creating user with invalid password should fail
[Arguments] ${password} ${error}
Create user example ${password}
Status should be Creating user failed: ${ERROR}
A user has a valid account
Create valid user ${USERNAME} ${PASSWORD}
She changes her password
Change password ${USERNAME} ${PASSWORD} ${NEW PASSWORD}
Status should be SUCCESS
She can log in with the new password
Login ${USERNAME} ${NEW PASSWORD}
She cannot use the old password anymore
Attempt to login with credentials ${USERNAME} ${PASSWORD}
Status should be Access Denied
Clear Login Database
Truncate
*** Variables ***
${USERNAME} janedoe
${PASSWORD} J4n3D0e
${error} 123456
${NEW PASSWORD} e0D3n4J
${DATABASE FILE} ${TEMPDIR}${/}robotframework-quickstart-db.txt
${PWD INVALID LENGTH} Password must be 7-12 characters long
${PWD INVALID CONTENT} Password must be a combination of lowercase and uppercase letters and numbers
${ERROR} Creating user failed: Password must be 7-12 characters long
*** Settings ***
Suite Setup Clear Login Database
Test Teardown Clear Login Database
Force Tags quickstart
Default Tags example smoke
Library OperatingSystem
Library ../Lib/LoginLibrary.py
__ `Creating test libraries`_
运行rst配置文件
E:\Projects\studyproject>robot QuickStart.rst
robot QuickStart.rst 到运行login.py分析
Demo大致的思路是这样的:
解析用户关键字 -> 查找函数关键字 -> 函数关键字对应的类库函数 -> 运行关键字(通过特定指令,也可以理解为关键字) -> 找到需要执行的模块函数 -> 在模块函数中进行对象操作,管理
这里_run_command通过Popen来执行执行模块中的函数
个人理解,运行robot QuickStart.rst 时,可能也是构造了一个类库对象,类似如下:
obj = LoginLibrary(),有对象后,就可以调用方法了:
obj.create_user('username', 'password')
需要注意.rst文件中关键词和类库函数之间的映射关系:关键词中的空格等同类库函数名称中的下划线 _,一个空格可以对应多个下划线,一个下划线似乎可以对应多个关键词单词之间的空格,不分字母大小写。
参考连接:
https://github.com/robotframework/QuickStartGuide/blob/master/QuickStart.rst