Selenium Web自动化实践案例

1、项目背景

https://passport.csdn.net/login CSDN登录页面

2、功能实现

· 自动运行用例

· 自动生成测试报告

· 自动断言与截图

· 自动将最新测试报告发送到指定邮箱

· 数据,页面元素分离

· PageObject+Unittest+ddt数据驱动用例

· 执行日志、分布式执行

3、项目架构

在这里插入图片描述
4、浏览器Driver定义

from common.readFile import ReadFile

from common.logger import Logger

from selenium import webdriver

logger = Logger()

from selenium.webdriver import Remote

class Browser():

def init(self):

config = ReadFile()

self.browser = config.readConfig(“Browser”, “browser”)

self.host = config.readConfig(“host”,“host”)

logger.info(“You had select {} host {} browser.”.format(self.host,self.browser))

def driver(self):

“”"

启动浏览器驱动

:return: 返回浏览器驱动URL

“”"

try:

driver = webdriver.Chrome()

driver = Remote(command_executor=‘http://’ + self.host + ‘/wd/hub’,

desired_capabilities={ ‘platform’: ‘ANY’,

‘browserName’: self.browser,

‘version’: “”,

‘javascriptEnabled’: True

}

)

return driver

except Exception as msg:

print(“驱动异常-> {0}”.format(msg))

5、用例运行前后的环境准备工作

import unittest

from common.driver import Browser

class StartEnd(unittest.TestCase):

def setUp(self):

self.driver = Browser().driver()

self.driver.implicitly_wait(10)

self.driver.maximize_window()

def tearDown(self):

self.driver.quit()

6、工具方法模块

主要封装一些公共的方法如:截图,查找最新报告。

import time

from selenium import webdriver

import os,sys

sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(file))))

from config import setting

def inser_img(driver):

指定截图存放的根目录路径

screen_dir = setting.TEST_REPORT + ‘/imges/’

rq = time.strftime(’%Y%m%d%H%M%S’, time.localtime(time.time()))

screen_name = screen_dir + rq + ‘.png’

driver.get_screenshot_as_file(screen_name)

print(‘screenshot:’ + screen_name)

#查找最新的测试报告

def latest_report(report_dir):

lists = os.listdir(report_dir)

lists.sort(key=lambda fn: os.path.getatime(report_dir + ‘\’ + fn))

file = os.path.join(report_dir, lists[-1])

return file

def latest_report_img(report_dir):

lists = os.listdir(report_dir)

lists.sort(key=lambda fn: os.path.getatime(report_dir + ‘\’ + fn))

file = os.path.join(report_dir, lists[-1])

return file

7、Pageobject页面对象封装

基础页面类

import time

from selenium import webdriver

from selenium.common.exceptions import NoSuchElementException

from common.logger import Logger

from common.readFile import ReadFile

logger = Logger()

class BasePage():

“定义一个页面基类,让所有页面都继承这个类,封装一些常用的页面操作方法到这个类”

def init(self, driver):

self.driver = driver

config = ReadFile()

self.baseurl = config.readConfig(“BaseUrl”, “url”)

def open_url(self, url):

self.driver.get(self.baseurl + url)

退出浏览器

def quit_browser(self):

self.driver.quit()

浏览器前进操作

def forward(self):

self.driver.forward()

浏览器后退操作

def back(self):

self.driver.back()

隐式等待

def wait(self, seconds):

self.driver.implicitly_wait(seconds)

查找元素

def find_element(self, selector):

selector_by = selector[‘find_type’]

selector_value = selector[‘element_info’]

try:

if selector_by == ‘id’:

el = self.driver.find_element_by_id(selector_value)

elif selector_by == “n” or selector_by == ‘name’:

el = self.driver.find_element_by_name(selector_value)

elif selector_by == ‘cs’ or selector_by == ‘css_selector’:

el = self.driver.find_element_by_css_selector(selector_value)

elif selector_by == ‘cn’ or selector_by == ‘classname’:

el = self.driver.find_element_by_class_name(selector_value)

elif selector_by == “lt” or selector_by == ‘link_text’:

el = self.driver.find_element_by_link_text(selector_value)

elif selector_by == “plt” or selector_by == ‘partial_link_text’:

el = self.driver.find_element_by_partial_link_text(selector_value)

elif selector_by == “tn” or selector_by == ‘tag_name’:

el = self.driver.find_element_by_tag_name(selector_value)

elif selector_by == “x” or selector_by == ‘xpath’:

el = self.driver.find_element_by_xpath(selector_value)

elif selector_by == “ss” or selector_by == ‘selector_selector’:

el = self.driver.find_element_by_css_selector(selector_value)

else:

raise NameError(“Please enter a valid type of targeting elements.”)

except NoSuchElementException :

logger.error("{0}页面中未能找到{1}元素".format(self, selector_value))

return el

输入

def input(self, selector, text):

el = self.find_element(selector)

try:

el.clear()

el.send_keys(text)

logger.info(“Had type ’ %s ’ in inputBox” % text)

except NameError as e:

logger.error(“Failed to type in input box with %s” % e)

点击

def click(self, selector):

el = self.find_element(selector)

try:

logger.info(“The element ’ %s ’ was clicked.” % el.text)

el.click()

except NameError as e:

logger.error(“Failed to click the element with %s” % e)

@staticmethod

def sleep(seconds):

time.sleep(seconds)

logger.info(“Sleep for %d seconds” % seconds)

def get_text(self,selector):

el = self.find_element(selector)

try:

return el.text

except NameError as e:

logger.error(“Failed to text the element with %s” % e)

def switch_frame(self, selector):

“”"

多表单嵌套切换

:param loc: 传元素的属性值

:return: 定位到的元素

“”"

try:

el = self.find_element(selector)

return self.driver.switch_to_frame(el)

except NoSuchElementException as e:

logger.error(“查找iframe异常-> {0}”.format(e))

def switch_windows(self, selector):

“”"

多窗口切换

:param loc:

:return:

“”"

try:

el = self.find_element(selector)

return self.driver.switch_to_window(el)

except NoSuchElementException as e:

logger.error(“查找窗口句柄handle异常-> {0}”.format(e))

def switch_alert(self):

“”"

警告框处理

:return:

“”"

try:

return self.driver.switch_to_alert()

except NoSuchElementException as e:

logger.error(“查找alert弹出框异常-> {0}”.format(e))

LoginPage.py —— CNDS登录页面

from pageObject.basePage import *

from selenium import webdriver

from common.readFile import ReadFile

from config import setting

login_el = ReadFile().readYaml(setting.TEST_Element_YAML + ‘/’ + ‘login.yaml’)

data = ReadFile().readYaml(setting.TEST_DATA_YAML + ‘/’ + ‘login_data.yaml’)

class CndsPage(BasePage):

‘’‘登录页面’’’

url = ‘/login’

定位器,通过元素属性定位元素对象

#选择账号密码登录

chanlelogin_loc = login_el[‘testcase’][0]

账号输入框

username_loc = login_el[‘testcase’][1]

密码输入框

pwd_loc = login_el[‘testcase’][2]

单击登录

login_accout_loc = login_el[‘testcase’][3]

def accout_login(self,accout,passwd):

self.open_url(self.url)

self.click(self.chanlelogin_loc)

self.input(self.username_loc,accout)

self.input(self.pwd_loc,passwd)

self.click(self.login_accout_loc)

定位器,通过元素属性定位检查项元素对象

user_login_success_loc = login_el[‘check’][0]

accout_id_loc = login_el[‘check’][1]

accout_pawd_error_loc = login_el[‘check’][2]

账号或密码错误提示

def accout_passwd_error(self):

return self.get_text(self.accout_pawd_error_loc)

登录成功,跳转到个人资料页,获取用户名

def get_account(self):

self.click(self.user_login_success_loc)

time.sleep(2)

def user_login_success(self):

return self.find_element(self.accout_id_loc).text

8、组织测试用例

· 用户名密码正确点击登录

· 用户名正确,密码错误点击登录

import unittest

from common import function,myUnit,readFile

from pageObject.loginPage import CndsPage

from time import sleep

from common.logger import Logger

from config import setting

import ddt

log = Logger()

testData= readFile.ReadFile().readYaml(setting.TEST_DATA_YAML + ‘/’ + ‘login_data.yaml’)

@ddt.ddt

class LoginTest(myUnit.StartEnd):

@unittest.skip(‘skip this case’)

“”“CNDS登录测试”""

def user_login_verify(self,account,passwd):

“”"

用户登录

:param :account 账号

:param passwd: 密码

:return:

“”"

CndsPage(self.driver).accout_login(account,passwd)

@ddt.data(*testData)

def test_login_normal(self,datayaml):

log.info(“test_login1_normal is start run…”)

self.user_login_verify(datayaml[‘data’][‘accout’],datayaml[‘data’][‘passwd’])

sleep(3)

#断言与截屏

po = CndsPage(self.driver)

if datayaml[‘screenshot’] == ‘login_success’:

po.get_account()

function.inser_img(self.driver)

self.assertEqual(po.user_login_success(), datayaml[‘check’][0], “登录成功,返回实际结果是->: {0}”.format(po.user_login_success()))

else:

function.inser_img(self.driver)

self.assertEqual(po.accout_passwd_error(), datayaml[‘check’][0],“登录失败,返回实际结果是->: {0}”.format(po.accout_passwd_error()))

print(“test_login1_normal is test end!”)

9、执行测试用例

import unittest

from common.function import latest_report

from common.sendMail import *

from config import setting

from thridLib.HTMLTestRunner import HTMLTestRunner

import time

import os,sys

sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(file))))

report_dir = setting.TEST_REPORT + ‘/report/’

def add_case(test_path=setting.TEST_DIR):

discover = unittest.defaultTestLoader.discover(test_path, pattern=“test*.py”)

return discover

def run_case(all_case,result_path=report_dir):

print(“start run testcase…”)

now = time.strftime("%Y-%m-%d %H_%M_%S")

report_name = result_path + ‘/’ + now + ‘result.html’

print(“start write report…”)

#HTMLTestRunner测试报告

with open(report_name, ‘wb’) as f:

runner = HTMLTestRunner(stream=f, title=‘测试报告’, description=‘用例执行情况’) # 定义测试报告

runner.run(all_case) # 执行测试用例

f.close()

print(“find latest report…”)

查找最新的测试报告

report = latest_report(result_path)

邮件发送报告

print(“send email report…”)

send_mail(report)

print(“test end!”)

if name == ‘main’:

cases = add_case()

run_case(cases)

在这里插入图片描述
一个用心码了这么多文字的人,往往渴望得到大家的认可。如果你觉得这篇文章对你有帮助,双击屏幕,给我点个赞呀!

更多软件测试资源分享微信公众号:【程序员阿沐】

软件测试技术交流群:810119819

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值