自动化测试实战
前言
- 借助开源的项目驱动Web自动化测试
- 有参考极客间里面郭老师的内容
- 欢迎加入python知识星球(附python web自动化教程)
一、环境搭建
- 项目架构
- Windows+Apache+Mysql+jpress
1.安装Apache
检验是否安装成功
浏览器输入127.0.0.1:8080 出现下面界面安装成功
2.安装Mysql
3.下载jpress
4.集成项目
- 将jpress文件源码放置Apache Tomcat webapps文件下
2.确保Mysql服务在运行并启动Apache服务器,浏览器进入http://127.0.0.1:8080/jpress/install
前台地址:http://127.0.0.1:8080/jpress
用户登录地址:http://127.0.0.1:8080/jpress/user/login
管理员登录地址:http://127.0.0.1:8080/jpress/admin/login
二、编写自动化脚本
1.需求分析
- 本项目测试的是一个开源的Java项目,测试的功能有
- 用户注册: http://127.0.0.1:8080/jpress/user/register
- 用户登录 : http://127.0.0.1:8080/jpress/user/login
- 后台管理员登录: http://127.0.0.1:8080/jpress/admin/login
- 文章分类:http://127.0.0.1:8080/jpress/admin/article/category
- 添加文章:http://127.0.0.1:8080/jpress/admin/article/write
- 本项目通过自动化测试的方法来验证,用户注册、用户登录、管理员登录、添加文章分类、添加文章、信息完整性、正确性。
2.用例设计
描述 | 步骤 | 预期结果 |
---|---|---|
验证有效的账号、邮箱、密码、确认密码、验证码进行注册登录 | 1.输入有效账号(wang) 2.输入有效邮箱(380590045@qq.com) 3.输入密码(w1234567w) 4.输入确认密码(w1234567w) 5.输入与之匹配的验证码 6.点击注册 | 注册成功,点击确认登录 |
验证无效的账号,有效的邮箱、密码、确认密码、验证码进行注册登录 | 1.用户为空 2.输入有效邮箱(380590045@qq.com) 3.输入密码(w1234567w) 4.输入确认密码(w1234567w) 5.输入与之匹配的验证码 6.点击注册 | 用户名不能为空 |
验证无效的账号,有效的邮箱、密码、确认密码、验证码进行注册登录 | 1.用户名重复 2.输入有效邮箱(380590045@qq.com) 3.输入密码(w1234567w) 4.输入确认密码(w1234567w) 5.输入与之匹配的验证码 6.点击注册 | 该用户名已经存在 |
验证有效的账号,无效的邮箱,有效的密码、确认密码、验证码进行注册登录 | 1.输入有效账号(zhang) 2.输入无效邮箱(123@qq.com) 3.输入密码(w1234567w) 4.输入确认密码(w1234567w) 5.输入与之匹配的验证码 6.点击注册 | 邮箱不正确 |
验证有效的账号,无效的邮箱,有效的密码、确认密码、验证码进行注册登录 | 1.输入有效账号(zhang) 2.输入无效邮箱重复(380590045@qq.com) 3.输入密码(w1234567w) 4.输入确认密码(w1234567w) 5.输入与之匹配的验证码 6.点击注册 | 该邮箱已经注册 |
验证有效的账号、邮箱,无效的密码,有效的确认密码、验证码进行注册登录 | 1.输入有效账号(zhang) 2.输入有效邮箱(3805900045@qq.com) 3.输入密码(1) 4.输入确认密码(1) 5.输入与之匹配的验证码 6.点击注册 | 请输入6-16位字母、数字组成的密码 |
验证有效的账号、邮箱、密码,无效的确认密码,有效的验证码进行注册登录 | 1.输入有效账号(zhang) 2.输入有效邮箱(3805900045@qq.com) 3.输入密码(w123456w) 4.输入确认密码(1) 5.输入与之匹配的验证码 6.点击注册 | 确认密码与密码不一致,请重新输入 |
验证有效的账号、邮箱、密码、确认密码,无效的验证码进行注册登录 | 1.输入有效账号(zhang) 2.输入有效邮箱(3805900045@qq.com) 3.输入密码(w123456w) 4.输入确认密码(w123456w) 5.输入验证码1234 6.点击注册 | 验证码不正确 |
验证在展示页评论有效内容填写和匹配验证码进行提交 | 1.点击文章(test) 2.评论栏输入123456 3.输入验证码 4.点击提交 | 评论直接显示下方 |
验证在展示页评论无效内容填写和匹配验证码进行提交 | 1.点击文章(test) 2.评论栏为空 3.输入验证码 4.点击提交 | 评论失败:评论内容不能为空 |
验证在展示页评论有效内容填写,无效验证码进行提交 | 1.点击文章(test) 2.评论栏输入123456 3.输入验证码1234 4.点击提交 | 评论失败:验证码错误 |
验证文章中投稿输入有效标题和内容进行保存投稿 | 1.输入标题testdemo 2.输入内容 this is testdemo 3.点击保存并投稿 | 文章保存成功 |
验证文章中投稿输入无效标题,有效内容进行保存投稿 | 1.标题为空 2.输入内容 this is testdemo 3.点击保存并投稿 | 操作失败,标题不能为空 |
验证文章中投稿输入有效标题,无效内容进行保存投稿 | 1.标题为testdemo 2.输入内容为空 3.点击保存并投稿 | 操作失败,文章内容不能为空 |
验证有效旧密码、输入有效密码、确认密码进行密码修改 | 1.输入有效旧密码admin 2.输入新密码admin 3.输入确认密码admin | 修改成功 |
验证无效旧密码、输入有效密码、确认密码进行密码修改 | 1.输入有效旧密码admin1 2.输入新密码admin1 3.输入确认密码admin | 密码错误 |
验证有效旧密码、输入有效密码、无效确认密码进行密码修改 | 1.输入有效旧密码admin 2.输入新密码admin1 3.输入确认密码admin | 两次出入密码不一致 |
验证删除单个文章 | 1.勾选文章框 2.点击批量删除 3.点击确定 | 文章数量少1 |
验证删除多个文章 | 1.勾选文章框 2.点击批量删除 3.点击确定 | 文章数为0 |
3.编写代码
- 项目架构设计
- Lib 第三方库
- chaojiying.py(超级鹰图片处理平台)
- Reports 测试报告
- Screenshots 截屏
- Testcases 测试用例
- both_link(存放关联登录后的操作测试用例)
- no_link_login(不需要关联登录的操作的测试用例)
- both_link(存放关联登录后的操作测试用例)
- main.py
- Lib 第三方库
#chaojiying.py
#!/usr/bin/env python
# coding:utf-8
import requests
from hashlib import md5
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf8')
self.password = md5(password).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
return r.json()
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
if __name__ == '__main__':
chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰用户名的密码', '96001') # 用户中心>>软件ID 生成一个替换 96001
im = open('a.jpg', 'rb').read() # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
print(chaojiying.PostPic(im, 1902))
#1902 验证码类型 官方网站>>价格体系 3.4+版 print 后要加()
#both_link
#test_commitcomment.py
import unittest,time
from testcases.no_link_login import test_login_user
from testcases.link_login import test_commitpl
class Test_commitcomment(unittest.TestCase):
def test_commit_success(self):
userLogincase = test_login_user.Test_login('test_success')
changpwd = test_commitpl.Test_commit('test_commitsuccess', userLogincase)
suite = unittest.TestSuite()
suite.addTest(userLogincase)
suite.addTest(changpwd)
runner = unittest.TextTestRunner().run(suite)
def test_commit_fail1(self):
userLogincase = test_login_user.Test_login('test_success')
changpwd = test_commitpl.Test_commit('test_commitfail1', userLogincase)
suite = unittest.TestSuite()
suite.addTest(userLogincase)
suite.addTest(changpwd)
runner = unittest.TextTestRunner().run(suite)
def test_commit_fail2(self):
userLogincase = test_login_user.Test_login('test_success')
changpwd = test_commitpl.Test_commit('test_commitfail2', userLogincase)
suite = unittest.TestSuite()
suite.addTest(userLogincase)
suite.addTest(changpwd)
runner = unittest.TextTestRunner().run(suite)
if __name__ == '__main__':
unittest.main()
#no_link_login
#test_login_user.py
from selenium import webdriver
import unittest
from lib.make_UserPwd import Create_username
from time import sleep
class Test_login(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
#浏览器初始化
cls.driver=webdriver.Chrome()
#url
cls.driver.get('http://127.0.0.1:8080/jpress/user/login')
#隐式等待
cls.driver.implicitly_wait(2)
#全屏
cls.driver.maximize_window()
#登录成功
def test_success(self):
#记录清除
self.driver.find_element_by_name('user').clear()
#账号定位
name='admin'
self.driver.find_element_by_name('user').send_keys(name)
#密码框定位
self.driver.find_element_by_name('pwd').clear()
self.driver.find_element_by_name('pwd').send_keys('admin')
#点击登录
self.driver.find_element_by_css_selector('body > div > div > div > form > div.row > div > button').click()
#断言
try:
excepted="您好 {} , 欢迎回来".format(name)
result=self.driver.find_element_by_css_selector('body > div > header > nav > div > ul > li.dropdown.user.user-menu > a > span')
self.assertEqual(result.text,result)
except BaseException as e:
print(e)
#登录失败,用户名不正确
def test_fail(self):
#随机生成用户名
username=Create_username()
#定位账号输入
self.driver.find_element_by_name('user').clear()
self.driver.find_element_by_name('user').send_keys(username)
#密码框定位
self.driver.find_element_by_name('pwd').clear()
self.driver.find_element_by_name('pwd').send_keys('admin')
#点击登录
self.driver.find_element_by_css_selector('body > div > div > div > form > div.row > div > button').click()
#强制休息2s
sleep(2)
#断言
try:
excepted="用户名不正确。"
result=self.driver.switch_to.alert
self.assertEqual(result.text,excepted)
except BaseException as e:
print(e)
#登录失败,用户名或密码不正确
def test_fail2(self):
username = "admin"
# 定位账号输入
self.driver.find_element_by_name('user').clear()
self.driver.find_element_by_name('user').send_keys(username)
#随机生成密码
pwd=Create_username()
# 密码框定位
self.driver.find_element_by_name('pwd').clear()
self.driver.find_element_by_name('pwd').send_keys(pwd)
# 点击登录
self.driver.find_element_by_css_selector('body > div > div > div > form > div.row > div > button').click()
# 强制休息2s
sleep(2)
# 断言
try:
excepted ="用户名或密码不正确"
result = self.driver.switch_to.alert
self.assertEqual(result.text, excepted)
except BaseException as e:
print(e)
#登录失败,账号不能为空
def test_fail3(self):
username = ""
# 定位账号输入
self.driver.find_element_by_name('user').clear()
self.driver.find_element_by_name('user').send_keys(username)
# 随机生成密码
pwd = Create_username()
# 密码框定位
self.driver.find_element_by_name('pwd').clear()
self.driver.find_element_by_name('pwd').send_keys(pwd)
# 点击登录
self.driver.find_element_by_css_selector('body > div > div > div > form > div.row > div > button').click()
# 强制休息2s
sleep(2)
# 断言
try:
excepted = "账号不能为空"
result = self.driver.switch_to.alert
self.assertEqual(result.text, excepted)
except BaseException as e:
print(e)
#登录失败,密码不能为空
def test_fail4(self):
username = "admin"
# 定位账号输入
self.driver.find_element_by_name('user').clear()
self.driver.find_element_by_name('user').send_keys(username)
# 随机生成密码
pwd = Create_username()
# 密码框定位
self.driver.find_element_by_name('pwd').clear()
self.driver.find_element_by_name('pwd').send_keys(pwd)
# 点击登录
self.driver.find_element_by_css_selector('body > div > div > div > form > div.row > div > button').click()
# 强制休息2s
sleep(2)
# 断言
try:
excepted = "密码不能为空"
result = self.driver.switch_to.alert
self.assertEqual(result.text, excepted)
except BaseException as e:
print(e)
if __name__ == '__main__':
unittest.main()
-这里就贴部分代码,所有的代码将会在Python知识星球分享(一个Python自学知识分享的平台,您的加入更多的是分享与互动)
- 代码的需要优化处
- 关联登录的操作出现重复代码
- 没有写log日志
- 没有做数据驱动
- 生成测试报告会出现两处地方
- 部分代码没有做备注
三、执行自动化脚本
#main.py
import unittest,time
from unittestreport import TestRunner
if __name__ == '__main__':
#调用unittest中defaultTestLoader中discover方法
# dis=unittest.defaultTestLoader.discover('./testcases/no_login',pattern='test_*.py')
dis=unittest.defaultTestLoader.discover('./testcases/both_link/',pattern='test*.py')
#时间戳
nowtime = time.strftime("%Y_%m_%d %H_%M_%S")
file_name = nowtime + 'report.html'
with open(file_name, 'wb') as f:
# 实例化
TestRunner(dis, filename=file_name, title="测试用例报告", tester="lw").run(3)