整理了一下自动化测试框架的摸索过程,作为笔记记录,也希望能给别人一些启发:
一、先实现一个简单用例的自动化
首先自己作为练习,可以先写个简单的自动化测试用例(例如,登录功能:打开网站,输入用户名、密码,登录,并验证登录成功),目前是把测试代码和页面元素都写在一个类文件里面(如下图)。参考文章:Python+Selenium自动化测试脚本(入门),先找下自动化测试的感觉,但是这样做的层次不清晰,无法同时支持多个人编写自动化脚本开发,我们一步步来摸索完善。
思路:
计划把web ui对象仓库从测试脚本中分离出来,使业务代码和测试脚本分离,即所谓的POM Structure(Page Object Model页面模型)。
这样做:
(1)每一个页面对应一个页面类,对应的页面元素写到这个页面类中
(2)页面类主要包括该页面的元素定位,和这些元素相关的业务操作代码封装方法
(3)代码可以复用,从而减少测试脚本代码量
二、具体操作实现:
1.浏览器驱动下载:所有驱动下载完成后,创建工程目录tools,将驱动发在该文件下。
(1).下载IE浏览器驱动地址:
http://selenium-release.storage.googleapis.com/index.html
(2).下载Chrome浏览器驱动地址:
https://sites.google.com/a/chromium.org/chromedriver/downloads
(3).下载Firefox浏览器驱动地址:
https://github.com/mozilla/geckodriver/releases
可能会遇到的问题:浏览器与驱动版本要匹配
2.创建framework(Python Package),作为基本的公共函数库,把跟系统相关的东西放在这个目录下。
(1)首先定义一个页面基类,让所有页面都继承这个类,封装一些常用的页面操作方法到这个类,可以包括浏览器操作、页面元素定位和操作、鼠标操作、键盘操作、cookies操作、窗口和frame操作等相关函数,我目前先放了这些内容,后续可以在使用过程中完善。创建base_page.py,结构如下:
代码实现:
coding=utf-8
class BasePage(object):
# region 初始化
def __init__(self, driver):
self.driver = driver
# endregion
# region 浏览器操作
# quit browser and end testing
def quit_browser(self):
self.driver.quit()
# endregion
(2)定义浏览器操作驱动库:创建browser_engine.py,其中open_browser方法用于自动读取config中的浏览器配置,打开指定测试url地址,quit_browser用于退出浏览器引擎。
代码实现:
# -*- coding:utf-8 -*-
import ConfigParser
from selenium import webdriver
import os
class BrowserEngine(object):
dir = os.getcwd()
chrome_driver_path = os.path.join(os.path.dirname(__file__), '../tools/chromedriver.exe').replace('\\', '/')
ie_driver_path = dir + '\\tools\\IEDriverServer.exe'
firefox_driver_path = dir + '\\tools\\geckodriver.exe'
def __init__(self, driver):
self.driver = driver
# pf.copy_file(self.firefox_driver_path, 'C:\\Python27\\geckodriver.exe')
# read the browser type from config.ini file, return the driver
def open_browser(self, driver):
config = ConfigParser.ConfigParser()
path = os.path.join(os.path.dirname(__file__), '../config/config.ini').replace('\\', '/')
config.readfp(open(path))
browser = config.get('browserType', 'browserName')
url = config.get('testServer', 'URL')
if browser == "Firefox":
# kill_process('firefox.exe')
# driver = webdriver.Firefox(self.firefox_driver_path)
driver = webdriver.Firefox()
elif browser == "Chrome":
# kill_process('chrome.exe')
# kill_process('chromedriver.exe')
driver = webdriver.Chrome(self.chrome_driver_path)
elif browser == "IE":
# kill_process('iexplore.exe')
driver = webdriver.Ie(self.ie_driver_path)
driver.get(url)
driver.maximize_window()
driver.implicitly_wait(10)
return driver
def quit_browser(self):
self.driver.quit()
3.创建config文件,放置浏览器配置文件。
4.新建PageObject文件夹,把各个页面元素放在该目录下。
为了方便管理,可按页面创建Python Package,目前我是创建了一个登录module,把登录相关的页面放到该包下,每个界面类中通常会包括以下三部分内容:
(1).页面元素定位(WebElements)
(2).页面元素操作和业务操作(Actions)
(3).验证点检查(Checkpoint)
代码实现:
# coding=utf-8
import unittest
from selenium.webdriver.common.by import By
from framework.base_page import BasePage
class LoginPage(BasePage):
# region 页面元素
user_id = (By.ID, 'loginFullEmail')
user_pwd = (By.ID, 'loginFullPwd')
login_button = (By.ID, 'btnFullLogin')
home_page_title = (By.CLASS_NAME, 'telemedicine-navbar-title')
# endregion
#输入用户名
def set_username(self, username):
name = self.driver.find_element(*self.user_id)
name.send_keys(username)
#输入密码
def set_password(self, password):
name = self.driver.find_element(*self.user_pwd)
name.send_keys(password)
#点击登录按钮
def click_login_btn(self):
login_btn = self.driver.find_element(*self.login_button)
login_btn.click()
# 获取登录后标题
def get_home_page_title(self):
title = self.driver.find_element(*self.home_page_title)
return title.text
# 验证登录成功
def verify_login_success(self, expected):
actual = self.get_home_page_title()
result = bool(actual == expected)
return result
if __name__ == '__main__':
unittest.main()
可能遇到的问题:
(1)无法导入自己创建的包(Python Package),解决办法:选择待导入的包,右键—Mark Directory as—Sources Root
(2)定义完页面元素后,使用self.driver.find_element调用元素,如果写成self.driver.find_element(self.user_id)无法识别到元素,解决办法:在对象前面加星号,如:self.driver.find_element(*self.user_id),详见:https://blog.csdn.net/ct745363083/article/details/100301039
5.创建测试脚本:
创建testsuits目录,将所需要测试的测试脚本放置到该目录下,每一个测试脚本采用unittest的策略分为三个部分:
初始化:setUp()
用例主体部分:test_xxx
收尾:tearDown()
代码实现:
# coding=utf-8
import unittest
from framework.broswer_engine import BrowserEngine
from pageobjects.LoginModule.LoginPage import LoginPage
import time
class HomePageLogin(unittest.TestCase):
# region 测试初始化
def setUp(self):
browser = BrowserEngine(self)
self.driver = browser.open_browser(self)
# endregion
# region 测试收尾
def tearDown(self):
self.driver.quit()
# endregion
def test_login(self):
# 页面实例化
login_page = LoginPage(self.driver)
# 页面操作
login_page.set_username('s1') # 输入用户名
login_page.set_password('1') # 输入密码
login_page.click_login_btn() #点击登录按钮
time.sleep(15)
login_page.verify_login_success(u'肿瘤专科远程医疗')
time.sleep(5)
if __name__ == '__main__':
unittest.main()
6.自此把基本的东西整理得差不多了,剩下来的东西要逐渐丰富起来,接下来的计划:
(1) 添加日志库Logger,记录测试步骤;
(2)创建通用的函数库(public_functions),把一些跟测试相关的方法,如目录操作、文件操作、系统相关操作放在该库中;
(3)把测试数据从测试脚本中分离出来,降低维护成本,暂时想的是维护在excel文件中;
(4)自动化测试报告生成及邮件发送;
(5)持续化集成处理。