python+selenium+unittest自动化测试框架

news2024/11/15 8:44:00
前言

关于自动化测试的介绍,网上已有很多资料,这里不再赘述,UI自动化测试是自动化测试的一种,也是测试金字塔最上面的一层,selenium是应用于web的自动化测试工具,支持多平台、多浏览器、多语言来实现自动化,优点如下:

①开源、免费且对web界面有良好的支持;;

②多浏览器支持:chrome、Firefox、IE、Edge等;

③多平台支持:Linux、Windows、MAC;

④多语言支持:java、python、Ruby、C#、JavaScript、C++;

⑤简单(API简单)、灵活(开发语言驱动),支持分布式测试用例执行;

环境准备
  • 浏览器(Chrome)
  • Python
  • Selenium
  • chromedriver(请下载于Chrome对应版本的驱动)
  • IDE(Pycharm)

1、python、pycharm安装

2、selenium安装

pip install selenium ​

关于selenium元素定位是开展web自动化测试的基础和关键,总共有八种定位方式,包括id,class,xpath等

3、chromedriver驱动安装

驱动下载:http://chromedriver.storage.googleapis.com/index.html

然后把chromedriver.exe拷贝到到chrome的安装目录下…\Google\Chrome\Application\ ,同时把chrome的安装目录加入到path环境变量。

4、快速验证测试

自动化测试框架

  • config目录中存放的是测试配置相关的文件,文件类型ini,包括测试的网址、浏览器驱动等信息
  • framework目录中存放的是页面基础类base_page: 封装一些常用的页面操作方法;日志类 Logger: 封装日志输出及控制台输出方法
  • logs用来存放输出的日志文件
  • pageobjects目录存放的是页面对象,一个页面封装为一个类,一个元素封装为一个方法
  • screenshots目录存放的是测试过程中的相关截图
  • test_report用来存放输出的测试报告
  • testsuites目录存放测试用例,包括test_base和单个测试用例

1、config.ini配置信息如下:

2、framework目录下base_page的封装:


import time

from selenium.webdriver.common.action_chains import ActionChains

from selenium.webdriver.support.wait import WebDriverWait

from selenium.webdriver.support.select import Select

import os.path

from framework.logger import Logger


# 创建一个日志实例

logger = Logger(logger="BasePage").getlog()


class BasePage(object):

"""

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

"""

def __init__(self, driver):

self.driver = driver


#get an url link

def open(self,url):

self.driver.get(url)


#quit browser and end testing

def quit_browser(self):

self.driver.quit()


# 浏览器前进操作

def forward(self):

self.driver.forward()

logger.info("Click forward on current page.")


# 浏览器后退操作

def back(self):

self.driver.back()

logger.info("Click back on current page.")


# 显示等待

def wait(self,loc,seconds):

try:

wait_=WebDriverWait(self.driver,seconds)

wait_.until(lambda driver:driver.find_element(*loc))

logger.info("wait for %d seconds." % seconds)

except NameError as e:

logger.error("Failed to load the element with %s" % e)


# 保存图片

def get_windows_img(self):

"""

把file_path保存到我们项目根目录的一个文件夹.\Screenshots下

"""

file_path = os.path.dirname(os.path.abspath('.')) + 'Selenium/screenshots/'

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

screen_name = file_path + rq + '.png'

try:

self.driver.get_screenshot_as_file(screen_name)

logger.info("Had take screenshot and save to folder : /screenshots")

except NameError as e:

logger.error("Failed to take screenshot! %s" % e)

self.get_windows_img()


# 定位元素方法

def find_element(self,loc):

"""

:return: element

"""

return self.driver.find_element(*loc)


# 输入

def send_keys(self, selector, text):


el = self.find_element(selector)

el.clear()

try:

el.send_keys(text)

logger.info("Had type \' %s \' in inputBox" % text)

except NameError as e:

logger.error("Failed to select in input box with %s" % e)

self.get_windows_img()


# 清除文本框

def clear(self, selector):


el = self.find_element(selector)

try:

el.clear()

logger.info("Clear text in input box before typing.")

except NameError as e:

logger.error("Failed to clear in input box with %s" % e)

self.get_windows_img()


# 点击元素

def click(self, selector):


el = self.find_element(selector)

try:

el.click()

logger.info("The element \'%s\' was clicked." % el.text)

except NameError as e:

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



#鼠标事件(左键点击)

def move_element(self,loc,sloc):

mouse=self.find_element(loc)

try:

ActionChains(self.driver).move_to_element(mouse).perform()

self.click(sloc)

pass

except Exception as e:

logger.error("Failed to click move_element with %s" % e)

self.get_windows_img()


# 强制等待

@staticmethod

def sleep(seconds):

time.sleep(seconds)

logger.info("Sleep for %d seconds" % seconds)

 logger日志输入方法:


import logging

import os.path

import time


class Logger(object):

def __init__(self, logger):

'''''

指定保存日志的文件路径,日志级别,以及调用文件

将日志存入到指定的文件中

'''

# 创建一个logger

self.logger = logging.getLogger(logger)

self.logger.setLevel(logging.DEBUG)


# 创建一个handler,用于写入日志文件

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

log_path = os.path.dirname(os.path.abspath('.')) + 'Selenium/logs/'

log_name = log_path + rq + '.log'

fh = logging.FileHandler(log_name)

fh.setLevel(logging.INFO)


# 再创建一个handler,用于输出到控制台

ch = logging.StreamHandler()

ch.setLevel(logging.INFO)


# 定义handler的输出格式

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

fh.setFormatter(formatter)

ch.setFormatter(formatter)


# 给logger添加handler

self.logger.addHandler(fh)

self.logger.addHandler(ch)


def getlog(self):

return self.logger

3、关于页面对象的写法参考:

页面对象继承于base_page基类


from framework.base_page import BasePage

from selenium.webdriver.common.by import By

from framework.logger import Logger


logger = Logger(logger="cloud_page").getlog()

class Cloud(BasePage):

#定位器

input_box = (By.ID,'kw')

search_submit = (By.XPATH,'//*[@id="su"]')


def value_input(self, text):

self.wait(self.input_box,5)

self.send_keys(self.input_box, text)


def submit_btn(self):

self.click(self.search_submit)

logger.info("show results!")

self.sleep(2)

4、testsuite部分,每个用例都要执行的用例前的准备setup和清理teardown写在test_base文件里,单个测试用例文件继承于它


from selenium import webdriver

import unittest


class TestBase(unittest.TestCase):

def setUp(self):

self.driver=webdriver.Chrome() #驱动浏览器

self.driver.implicitly_wait(10) #设置隐式等待

self.driver.maximize_window() #最大化浏览器


def tearDown(self):

self.driver.quit()


if __name__=='__main__':

unittest.main()

测试用例参考,注意测试用例方法命名一定要以test开头


import time

from testsuites.test_base import TestBase

from pageobjects.baidu_page import Cloud


class BaiduSearch(TestBase):


def test_baidu_search(self):

"""

这里一定要test开头,把测试逻辑代码封装到一个test开头的方法里。

:return:

"""

input = Cloud(self.driver)

input.open('https://www.baidu.com/')

input.value_input('selenium') # 调用页面对象中的方法

input.submit_btn() # 调用页面对象类中的点击搜索按钮方法

time.sleep(2)

input.get_windows_img() # 调用基类截图方法

try:

assert 'selenium' in 'selenium'

print('Test Pass.')

except Exception as e:

print('Test Fail.', format(e))

5、最后就是核心代码,testrunner.py 用来批量执行测试用例,引用HTMLTestRunner模块生成测试报告。


import unittest

from HTMLTestRunner import HTMLTestRunner

import time

import os


# 定义输出的文件位置和名字

DIR = os.path.dirname(os.path.abspath(__file__))

now = time.strftime("%Y%m%d%H%M", time.localtime(time.time()))


filename =now+"report.html"

#discover方法执行测试套件

testsuite = unittest.defaultTestLoader.discover(

start_dir='./testsuites',

pattern='*case.py',

top_level_dir=None

)


with open(DIR+'/test_report/'+filename,'wb') as f:

runner = HTMLTestRunner(

stream=f,

verbosity=2,

title='gateway UI report',

description='执行情况',

tester='tester'

)

runner.run(testsuite)

6、测试报告展示

总结

基于selenium实现的web自动化框架不仅轻量级而且灵活,可以快速的开发自动化测试用例。本篇中的框架设计比较简单,希望对大家以后的web自动化框架的设计和实现有所帮助,共同交流,共同进步!

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1963990.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【实战】SpringBoot整合ffmpeg实现动态拉流转推

SpringBoot整合ffmpeg实现动态拉流转推 在最近的开发中,遇到一个 rtsp 协议的视频流,前端vue并不能直接播放,因此需要对流进行处理。在网上查阅后,ffmpeg和webrtc是最多的解决方案,但是使用webrtc的时候没成功&#x…

交通 | 不确定条件下旅行者路径选择的K阶均值偏差模型

摘要 现实世界中的交通网络通常具有随机特性,旅行时间可靠性自然成为影响旅行者路线选择的关键因素。在这种情况下,仅凭平均路径旅行时间可能无法充分代表路径对旅行者的吸引力,本研究引入了 k k k 阶均值偏差模型,用于优化大型…

紫辉创投开启Destiny of Gods首轮投资,伯乐与千里马的故事仍在继续

近日,上海紫辉创业投资有限公司(以下简称“紫辉创投”)宣布开启GameFi链游聚合平台Destiny of Gods首轮投资500,000美金,并与其达成全面战略及业务层合作,双方将协同布局链上生态,共同推动链游行业健康发展…

研究人员可以采用什么策略来批判性地评估和综合其领域的不同文献

VersaBot Literature Review 一键生成文献综述 研究人员可以采用各种策略来批判性地评估和综合其领域内的不同文献; 评估策略 审查方法论: 分析每个来源中使用的研究设计、样本选择、数据收集和分析方法。考虑每种方法的潜在偏见、局限性和优势。评估…

宝通科技携手昇腾技术首席陈仲铭,共探工业大模型与生态发展

在人工智能技术的浪潮中,宝通科技始终致力于探索和应用前沿技术,推动工业智能化的发展。7月26日,宝通科技特邀昇腾生态技术首席陈仲铭博士,为宝通员工带来了一场主题为《工业大模型与业界发展生态》的技术分享会。本次分享会不仅为…

从CNN到Transformer:基于PyTorch的遥感影像、无人机影像的地物分类、目标检测、语义分割和点云分类教程

原文链接:从CNN到Transformer:基于PyTorch的遥感影像、无人机影像的地物分类、目标检测、语义分割和点云分类教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247610610&idx5&snf973c3e430c89d6123ca8f4892086c55&chksmfa8271…

nameparser,一个强大的 Python 库!

更多资料获取 📚 个人网站:ipengtao.com 大家好,今天为大家分享一个强大的 Python 库 - nameparser。 Github地址:https://github.com/derek73/python-nameparser 在处理用户数据时,尤其是涉及到用户姓名的场景下&am…

最佳需求管理工具:2024年10大主流工具

本文将分享2024年排名靠前的10款需求管理工具:PingCode、Worktile、Teambition、TAPD、禅道、明道云、CODING、Jama Connect、Jira、Codebeamer。 在选择需求管理工具时,你是否感到不知从何下手?面对市场上数不清的选项,确定哪一款…

远程办公访问优化指南:如何打造高效企业组网

当今数字化时代,远程办公已成为许多企业不可或缺的工作模式。面对地理位置分散、网络环境复杂等挑战,如何打造高效、稳定、安全的企业组网,成为企业IT部门亟需解决的问题。本文将为您提供一份远程办公访问优化指南,帮助您构建高效…

坐牢二十天 20240731(IO)

一.作业 1> 使用父子进程完成两个文件的拷贝 父进程拷贝前一半内容&#xff0c;子进程拷贝后一半内容 子进程结束后退出&#xff0c;父进程回收子进程的资源 #include <myhead.h> //定义求源文件长度的函数 int lenmain(const char *src,const char *dst) {int fd…

各类基于虚拟主机的应用及上线商城系统

一、基于域名访问 查看没有空行&#xff0c;没有注释的文件内容 [rootweb ~]# grep -Ev "#|^$" /usr/local/nginx/conf/nginx.conf [rootweb ~]# cp /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.bak [rootweb ~]# grep -Ev "#|^$"…

temu插件丨temu插件下载免费体验-特喵数据

在当今这个日新月异的电商时代&#xff0c;每一个细微的洞察都可能是商家决胜千里的关键。随着跨境电商平台的蓬勃兴起&#xff0c;Temu作为一股不可忽视的新兴力量&#xff0c;正以其独特的模式和强大的数据分析能力&#xff0c;引领着行业的新风尚。接下来看看让您的Temu店铺…

解决TensorFlow非法指令 (核心已转储)问题

背景 测试环境使用TensorFlow 1.14.0运行实体抽取和事项要素项目正常&#xff0c;打包项目和miniconda3环境进行部署&#xff0c;进行predict时报错。然后使用dockerfile生成环境镜像进行部署&#xff0c;发现仍报错。最后查资料解决该问题。 Using TensorFlow backend. 非法指…

《CSS创意项目实战指南》:点亮网页,从实战中掌握CSS的无限创意

CSS创意项目实战指南 在数字时代&#xff0c;网页不仅是信息的载体&#xff0c;更是艺术与技术的融合体。通过CSS&#xff0c;你可以将平凡的网页转变为引人入胜的视觉盛宴&#xff0c;让用户体验跃升至全新高度。《CSS创意项目实战指南》正是这样一本引领你探索CSS无限可能的…

【全志H616开发】SQLite打开/创建数据库的C接口

文章目录 打开/创建数据库的C接口函数介绍sqlite3_open函数sqlite3_close函数sqlite3_errmsg函数 代码示例 打开/创建数据库的C接口函数介绍 sqlite3_open函数 sqlite3_open 是 SQLite 数据库库中的一个函数&#xff0c;用于打开一个新的数据库连接。如果指定的数据库文件不存…

大厂linux面试题攻略一之网络基础

一、网络基础类面试题 1.简述ISO/OSI七层模型&#xff08;理论模型&#xff09;的分层与作用 ISO&#xff1a;国际标准化组织 OSI&#xff1a;开放系统互联 第7层应用层&#xff1a;为用户提供服务&#xff0c;给用户一个操作界面 第6层表示层&#xff1a;数据提供表示、加密…

从零入门 AI for Science(AI+药物) #Datawhale AI 夏令营 Task2

书接上回: 从零入门 AI for Science&#xff08;AI药物) #Datawhale AI 夏令营 Task2 前面了解了赛题&#xff0c;这个主要讲baseline代码&#xff0c;入门RNN和特征工程 解读官方baseline set_random_seed 统一设置随机种子 def set_random_seed(seed):"""设…

一万亿token!34亿张图像,扩大10倍!史上最大开源多模态数据集MINT-1T发布!

众所周知&#xff0c;现在训练AI最需要的是什么&#xff1f; 数据&#xff0c;数据&#xff0c;还是数据。——毕竟只有让AI学好了&#xff0c;AI才能好好地回答你的问题&#xff0c;否则就会答非所问。 但是喂给AI的数据&#xff0c;现在和GPU一样&#xff0c;成了紧缺资源。…

Java:类集(List,Vector,Set,HashMap)

类集:就是一个动态的对象数组,是对一些实现好的数据结构的包装,这样在使用时会非常方便,而且最重要的是类集框架本身不受对象数组长度的限制。 类集的特性:(1)这种框架是高性能的,对基本类集(动态数组、链接表、树和散列表)的实现是高效率的。所以一般很少需要人工对…

汇舟问卷:从了解国外问卷工作室开始!

大家好&#xff0c;我是汇舟问卷。上个月有个互联网大厂上班的经理联系到我&#xff0c;向我们咨询了关于国外问卷调查工作室的情况。 他对当时稳定的生活状态感到担忧担忧&#xff1a;每月稳定的收入虽然足以应对家庭开支&#xff0c;却难以积蓄足够的资金&#xff0c;尤其是…