You have no idea, implement a Python + Selenium automated testing framework that simple!

 

First you have to know what is Selenium?

Selenium is a browser-based automated testing tool that provides a cross-platform, cross-browser web-to-end automation solutions. Selenium mainly includes three parts: Selenium IDE, Selenium WebDriver and Selenium Grid.

  • Selenium IDE: a Firefox extension, it can play back the recording, and the recording operation (e.g., Java, Python, etc.) into the form of test cases derived languages.

  • Selenium WebDriver: to provide the necessary automation Web API, mainly used browser control, select the page elements and debugging. Different browsers require different WebDriver.

  • Selenium Grid: provides the ability to run selenium tests on different machines in different browsers.

Now I will use mind mapping directory structure introduces basic testing framework, writing test cases for functional test cases, I want to help you learn.

Design ideas

Frame python3 + selenium3 + PO + yaml + ddt + unittest and other basic techniques for writing into a testing framework that can adapt to the routine testing needs.

  1. Use Page Object Location page mode and a separate business operations, the separation of the test object (target element), and a test script (script use cases), a page to build an object class, improving maintainability use cases;

  2. Use yaml management page controls elements of the data and test data. For example, an element ID is changed like, do not need to modify the test code, only need to modify the corresponding page element file yaml;

  3. Management sub-module, independently of each other, ready to assemble, used with that.

Testing framework hierarchical design

 

Find the common operations and packaged into a base class, no matter what the product can be directly used to multiplex

  • The main business layer is encapsulated target page class, a class to build a page, the page inherits the business layer base layer

  • It is constructed to perform simulation test cases for product pages function layer

  • Framework assembly base layer provides the support and the whole process execution function expansion, to provide data for each page element with a layer embodiment, case testing data, test reports etc. Output

Testing framework directory structure

 

FIG mind the following directory structure Introduction:

 

Written Example

如果对软件测试、接口测试、自动化测试、面试经验交流。感兴趣可以关注我们爱码小士,公众号内会有不定期的发放免费的资料链接,这些资料都是从各个技术网站搜集、整理出来的,如果你有好的学习资料可以私聊发我,我会注明出处之后分享给大家

testinfo:
- id: test_login001
title: 登录测试
info: 打开抽屉首页
testcase:
- element_info: login-link-a
find_type: ID
operate_type: click
info: 打开登录对话框
- element_info: mobile
find_type: ID
operate_type: send_keys
info: 输入手机号
- element_info: mbpwd
find_type: ID
operate_type: send_keys
info: 输入密码
- element_info: //input[@class='keeplogin']
find_type: XPATH
operate_type: click
info: 单击取消自动登录单选框
- element_info: //span[text()='登录']
find_type: XPATH
operate_type: click
info: 单击登录按钮
- element_info: userProNick
find_type: ID
operate_type: perform
info: 鼠标悬停账户菜单
- element_info: //a[@class='logout']
find_type: XPATH
operate_type: click
info: 选择退出
check:
- element_info: //div[@class='box-mobilelogin']
/div[1]/span
find_type: XPATH
info: 检查输入手机号或密码,登录异常提示
- element_info: userProNick
find_type: ID
info: 成功登录
- element_info: reg-link-a
find_type: ID
info: 检查退出登录是否成功
login.yaml

 

例如,我们要新增登录功能测试用例:

首先,只需在testyaml目录下新增一个页面对象yaml文件,参考login.yaml格式编写即可。这些文件是提供给封装页面对象类调用并执行定位识别操作。

-
id: test_login001.1
detail : 手机号和密码为空登录
screenshot : phone_pawd_empty
data:
phone: ""
password: ""
check :
- 手机号不能为空
-
id: test_login001.2
detail : 手机号为空登录
screenshot : phone_empty
data :
phone: ""
password : aa
check :
- 手机号不能为空
-
id: test_login001.3
detail : 密码为空登录
screenshot : pawd_empty
data :
phone : 13511112222
password: ""
check :
- 密码不能为空
-
id: test_login001.4
detail : 非法手机号登录
screenshot : phone_error
data :
phone : abc
password: aa
check :
- 手机号格式不对
-
id: test_login001.5
detail : 手机号或密码不匹配
screenshot : pawd_error
data :
phone : 13511112222
password: aa
check :
- 账号密码错误
-
id: test_login001.6
detail : 手机号和密码正确
screenshot : phone_pawd_success
data :
phone : 13865439800
password: ********
check :
- yingoja
login_data.yaml

login_data.yaml

 

其次,在testdata目录下新增一个login_data.yaml文件提供给登录接口传参的测试数据,编写格式参考login_data.yaml文件。

 

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'YinJia' 
import os,sys
sys.path.append(os.path.dirname(os.path.dirname
(os.path.dirname(__file__))))
from config import setting
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.action_chains 
import ActionChains
from selenium.webdriver.common.by import By
from public.page_obj.base import Page
from time import sleep
from public.models.GetYaml import getyaml
testData = getyaml(setting.TEST_Element_YAML
+ '/' + 'login.yaml')
class login(Page):
"""
用户登录页面
"""
url = '/'
dig_login_button_loc = (By.ID, testData.
get_elementinfo(0)) def dig_login(self):
"""
首页登录
:return:
"""
self.find_element(*self.dig_login_button_loc)
.click() sleep(1)
# 定位器,通过元素属性定位元素对象
# 手机号输入框
login_phone_loc = (By.ID,testData.
get_elementinfo(1)) # 密码输入框
login_password_loc = (By.ID,testData.
get_elementinfo(2)) # 取消自动登录
keeplogin_button_loc = (By.XPATH,testData.
get_elementinfo(3)) # 单击登录
login_user_loc = (By.XPATH,testData.
get_elementinfo(4)) # 退出登录
login_exit_loc = (By.ID, testData.
get_elementinfo(5)) # 选择退出
login_exit_button_loc = (By.XPATH,testData.
get_elementinfo(6))def login_phone(self,phone):
"""
登录手机号
:param username:
:return:
"""
self.find_element(*self.login_phone_loc).
send_keys(phone)def login_password(self,password):
"""
登录密码
:param password:
:return:
"""
self.find_element(*self.login_password_loc).
send_keys(password) def keeplogin(self):
"""
取消单选自动登录
:return:
"""
self.find_element(*self.keeplogin_button_loc).
click()def login_button(self):
"""
登录按钮
:return:
"""
self.find_element(*self.login_user_loc).click()
def login_exit(self):
"""
退出系统
:return:
"""
above = self.find_element(*self.login_exit_loc)
ActionChains(self.driver).move_to_element(above).
perform() sleep(2)
self.find_element(*self.login_exit_button_loc)
.click()def user_login(self,phone,password):
"""
登录入口
:param username: 用户名
:param password: 密码
:return:
"""
self.open()
self.dig_login()
self.login_phone(phone)
self.login_password(password)
sleep(1)
self.keeplogin()
sleep(1)
self.login_button()
sleep(1)
phone_pawd_error_hint_loc = (By.XPATH,testData.
get_CheckElementinfo(0))
user_login_success_loc = (By.ID,testData.
get_CheckElementinfo(1))
exit_login_success_loc = (By.ID,testData.
get_CheckElementinfo(2))
# 手机号或密码错误提示
def phone_pawd_error_hint(self):
return self.find_element(*self.phone_pawd_error_
hint_loc).text# 登录成功用户名
def user_login_success_hint(self):
return self.find_element(*self.user_login_
success_loc).text # 退出登录
def exit_login_success_hint(self):
return self.find_element(*self.exit_login_
success_loc).textloginPage.py

然后,在page_obj目录下新增一个loginPage.py文件,是用来封装登录页面对象类,执行登录测试流程操作。

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'YinJia' 
import os,sys
sys.path.append(os.path.dirname(os.path.
dirname(__file__)))
import unittest,ddt,yaml
from config import setting
from public.models import myunit,screenshot
from public.page_obj.loginPage import login
from public.models.log import Log
try:
f =open(setting.TEST_DATA_YAML + '/' + 'login_data.yaml',encoding='utf-8')
testData = yaml.load(f)
except FileNotFoundError as file:
log = Log()
log.error("文件不存在:{0}".format(file))
@ddt.ddt
class Demo_UI(myunit.MyTest):
"""抽屉新热榜登录测试"""
def user_login_verify(self,phone,password):
"""
用户登录
:param phone: 手机号
:param password: 密码
:return:
"""
login(self.driver).user_login(phone,password)
def exit_login_check(self):
"""
退出登录
:return:
"""
login(self.driver).login_exit()
@ddt.data(*testData)
def test_login(self,datayaml):
"""
登录测试
:param datayaml: 加载login_data登录测试数据
:return:
"""
log = Log()
log.info("当前执行测试用例ID-> {0} ; 测试点-> {1}".format(datayaml['id'],datayaml['detail']))
# 调用登录方法
self.user_login_verify(datayaml['data']['phone'],
datayaml['data']['password'])
po = login(self.driver)
if datayaml['screenshot'] == 'phone_pawd_success':
log.info("检查点-> {0}".format
(po.user_login_success_hint()))
self.assertEqual(po.user_login_success_hint(), datayaml['check'][0], "成功登录,返回实际结果是->: {0}".format(po.user_login_success_hint()))
log.info("成功登录,返回实际结果是->: {0}".format(po.user_login_success_hint()))
screenshot.insert_img(self.driver, datayaml
['screenshot'] + '.jpg')
log.info("-----> 开始执行退出流程操作")
self.exit_login_check()
po_exit = login(self.driver)
log.info("检查点-> 找到{0}元素,表示退出成功!".format(po_exit.exit_login_success_hint()))
self.assertEqual(po_exit.exit_login_success_hint(),
'注册',"退出登录,返回实际结果是->: {0}".format(po_exit.exit_login_success_hint()))
log.info("退出登录,返回实际结果是->: {0}".format(po_exit.exit_login_success_hint()))
else:
log.info("检查点-> {0}".format(po.phone
_pawd_error_hint()))
self.assertEqual(po.phone_pawd_error_hint(),
datayaml['check'][0] , "异常登录,返回实际结果是->: {0}".format(po.phone_pawd_error_hint()))
log.info("异常登录,返回实际结果是->: {0}".format(po.phone_pawd_error_hint()))
screenshot.insert_img(self.driver,datayaml
['screenshot'] + '.jpg')
if __name__=='__main__':
unittest.main()
login_sta.py

最后,在testcase目录下创建测试用例文件login_sta.py,采用ddt数据驱动读取yaml测试数据文件

综上所述,编写用例方法只需要按以上四个步骤创建->编写即可。

执行如下主程序,可看输出的实际结果。

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'YinJia' import os,sys
sys.path.append(os.path.dirname(__file__))
from config import setting
import unittest,time
from package.HTMLTestRunner import HTMLTestRunner
from public.models.newReport import new_report
from public.models.sendmail import send_mail
# 测试报告存放文件夹,如不存在,则自动创建
一个report目录 if not os.path.exists(setting.TEST_REPORT):os.makedirs
(setting.TEST_REPORT + '/' + "screenshot")
def add_case(test_path=setting.TEST_DIR):
"""加载所有的测试用例"""
discover = unittest.defaultTestLoader.discover
(test_path, pattern='*_sta.py')
return discover
def run_case(all_case,result_path=setting.TEST_REPORT):
"""执行所有的测试用例"""
now = time.strftime("%Y-%m-%d %H_%M_%S")
filename = result_path + '/' + now + 'result.html'
fp = open(filename,'wb')
runner = HTMLTestRunner(stream=fp,title='
抽屉新热榜UI自动化测试报告',
description='环境:windows 7 浏览器:chrome',
tester='Jason')
runner.run(all_case)
fp.close()
report = new_report(setting.TEST_REPORT)
#调用模块生成最新的报告
send_mail(report) #调用发送邮件模块
if __name__ =="__main__":
cases = add_case()
run_case(cases)

 

 

测试结果展示

HTML报告日志

 

HTML报告点击截图,弹出截图

 

测试报告通过的日志

 

自动截图存放指定的目录

 

邮件测试报告

 

Guess you like

Origin www.cnblogs.com/nanaheidebk/p/12409976.html