当前位置: 首页 > news >正文

网站备案地址不是我的地址怎么办/360优化大师软件

网站备案地址不是我的地址怎么办,360优化大师软件,wordpress文章添加链接地址,福建省网站备案结合前面的元素寻找、操作、unittest测试框架,搭建一个完整的自动化框架。本篇旨在框架设计、单机用例执行、输出报告,下篇继续实践Bat批处理执行测试、多设备并发测试。 框架功能 数据配置 日志输出 截图处理 基础功能封装(公共方法&…

结合前面的元素寻找、操作、unittest测试框架,搭建一个完整的自动化框架。本篇旨在框架设计、单机用例执行、输出报告,下篇继续实践Bat批处理执行测试、多设备并发测试。

框架功能

  • 数据配置

  • 日志输出

  • 截图处理

  • 基础功能封装(公共方法,查找元素)

  • 业务功能

  • 数据驱动

  • 测试用例封装

  • 断言处理和报告输出

测试需求

测试环境

  • win10
  • appium 1.17.1
  • weixin
  • 真机

测试用例

  • 登录场景1.用户名 xxx 密码 xxx (登录成功)
  • 登录场景2.用户名 xxx 密码 xxx (登录失败)

框架设计

在这里插入图片描述

代码实现

日志输出

# -*- coding:utf-8 -*-
# __author__ = "Cc"import logging
import timeclass OutputLog:critical = logging.CRITICAL  # 级别最高,什么也不输出fatal = logging.FATALerror = logging.ERRORwarning = logging.WARNINGinfo = logging.INFOdebug = logging.DEBUG@classmethoddef output_log(cls, log_level=debug):my_logging = logging.getLogger(__name__)my_logging.setLevel(log_level)if not my_logging.handlers:local_time = time.localtime()file_name1 = time.strftime('%Y-%m-%d', local_time)file_name2 = r"Logging\\"file_name = file_name2 + file_name1 + ".log"file_handler = logging.FileHandler(file_name, "a", encoding="utf-8")  # 输出日志到磁盘文件file_handler.setLevel(log_level)formatter = logging.Formatter("%(asctime)s--%(levelname)s--%(process)d--""%(thread)d--%(threadName)s--%(funcName)s--%(lineno)d--%(lineno)d : %(message)s")file_handler.setFormatter(formatter)my_logging.addHandler(file_handler)return my_logging

遇到的问题和解决方法

举个调用的例子:

OutputLog.output_log().debug("==============开始测试,连接手机==============")
OutputLog.output_log().debug("==============第二次调用==============")

上面代码,第一行日志输出只输出了一次,第二行输出了两次,原因是我在一开始实现时,每次调用都会重新创建一个handles,使用完后没有删除,同一log对象有多个handles,日志会重复输出,所以我在创建handles前先加以判断:if not my_logging.handlers,如果存在则不重新创建了。

设备初始化

设备信息

保存设备信息在devices.yaml中,可以通过修改此文件,修改设备信息。

oppo_findx_pro:appActivity: com.tencent.mm.ui.LauncherUIappPackage: com.tencent.mmautoGrantPermissions: trueautomationName: UiAutomator2chromeOptions:androidProcess: com.tencent.mm:toolsmpchromedriverExecutable: C:\Users\v_yddchen\Desktop\chromedriver_win32 77.0\chromedriver.exedeviceName: ddnoReset: falseplatFormVersion: 10platformName: AndroidresetKeyboard: trueudid: 648d4f29unicodeKeyboard: true
oppo_reno:appActivity: com.tencent.mm.ui.LauncherUIappPackage: com.tencent.mmautoGrantPermissions: trueautomationName: UiAutomator2chromeOptions:androidProcess: com.tencent.mm:toolsmpchromedriverExecutable: C:\Users\v_yddchen\Desktop\chromedriver_win32 77.0\chromedriver.exedeviceName: df93a63anoReset: falseplatFormVersion: 9platformName: AndroidresetKeyboard: trueudid: df93a63aunicodeKeyboard: true

初始化

初始化操作

# 初始化设备# -*- coding:utf-8 -*-
# __author__ = "Cc"from appium import webdriver
import yaml
from OutputLog import OutputLog
from login import Login
import timeclass InitDevices:def __init__(self, file_name, device_name):self.file_name = file_nameself.device_name = device_namedef read_devices(self):"""获取设备信息:return:"""try:OutputLog.output_log().debug("尝试获取设备信息")with open(self.file_name, 'r', encoding='utf-8') as f:all_devices = yaml.safe_load(f.read())except IOError:OutputLog.output_log().error("设备文件读取错误")else:msg = str(all_devices[self.device_name])OutputLog.output_log().debug(msg)return all_devices[self.device_name]def init_devices(self, device_info):"""初始化设备:param device_info::return:"""return webdriver.Remote("http://localhost:4723/wd/hub", device_info)if __name__ == "__main__":OutputLog.output_log().debug("==============开始测试,连接手机==============")devices_object = InitDevices('devices.yaml', 'oppo_findx_pro')devices_info = devices_object.read_devices()devices = devices_object.init_devices(devices_info)OutputLog.output_log().debug("连接成功")  # 连接成功,开始找元素file_name = 'screenshots/' + '测试' + '.png'devices.find_element_by_android_uiautomator('new UiSelector().textMatches("(.*)录")')devices.get_screenshot_as_file(file_name)devices.implicitly_wait(5)login_els = Login(devices)time.sleep(2)time.sleep(2)

获取测试数据

数据准备
在这里插入图片描述
读取数据

# 读取测试数据
# -*- coding:utf-8 -*-
# __author__ = "Cc"import csvclass ReadData:def __init__(self, file_name):self.file_name = file_namedef read_data(self):"""注意文件不能有中文,否则会报错:return: 二维数组data"""with open(self.file_name, 'r', encoding='utf-8') as f:csv_reader = csv.reader(f)head = next(csv_reader)# print(head)data = [[]]if len(data):data.clear()  # 如果没有这一步,data会存在一个空值for data1 in csv_reader:data.append(data1)else:for data1 in csv_reader:data.append(data1)# print(data)return dataif __name__ == "__main__":re = ReadData("login_msg.csv")re.read_data()

公共方法

寻找元素的公共方法的封装

# 基类,查找元素# -*- coding:utf-8 -*-
# __author__ = "Cc"from appium.webdriver import webdriver
from selenium.webdriver.common.by import By
from OutputLog import OutputLogclass BaseFindEl:def __init__(self, devices):"""传入设备:param devices:"""self.devices = devicesdef find_el_by_text(self, **kw):"""根据传入text时关键字参数的名称,决定调用text的哪一个方法:param kw: 查找元素的text:return: 返回找到的元素"""if 'text' in kw:text = kw['text']path = 'new UiSelector().text("{}")'.format(text)return self.devices.find_element_by_android_uiautomator(path)elif 'textContains' in kw:text = kw['textContains']path = 'new UiSelector().textContains("{}")'.format(text)return self.devices.find_element_by_android_uiautomator(path)elif 'textStarsWith' in kw:text = kw['textStarsWith']path = 'new UiSelector().textStarsWith("{}")'.format(text)return self.devices.find_element_by_android_uiautomator(path)elif 'textMatches' in kw:text = kw['textMatches']path = 'new UiSelector().textMatches("{}")'.format(text)return self.devices.find_element_by_android_uiautomator(path)else:OutputLog.output_log().error("没有匹配到查找方法")def find_el_by_class_name(self, **kw):"""根据传入的className查找元素:param kw: className:return: 找到的元素"""if 'className' in kw:text = kw['className']path = 'new UiSelector().className("{}")'.format(text)return self.devices.find_element_by_android_uiautomator(path)elif 'classNameContains' in kw:text = kw['classNameContains']path = 'new UiSelector().classNameContains("{}")'.format(text)return self.devices.find_element_by_android_uiautomator(path)else:OutputLog.output_log().error("没有匹配到查找方法")def find_el_by_resource_id(self, **kw):"""根据传入的resourceId查找元素:param kw::return:"""if 'resourceId' in kw:text = kw['resourceId']path = 'new UiSelector().resourceId("{}")'.format(text)return self.devices.find_element_by_android_uiautomator(path)elif 'resourceIdMatches' in kw:text = kw['resourceIdMatches']path = 'new UiSelector().resourceIdMatches("{}")'.format(text)return self.devices.find_element_by_android_uiautomator(path)else:OutputLog.output_log().error("没有匹配到查找方法")def find_el_by_multi_values(self, **values):"""组合多个属性:param values::return:"""pass

业务功能

# 查找登录界面所有的元素# -*- coding:utf-8 -*-
# __author__ = "Cc"from BaseFindEl import BaseFindEl
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from OutputLog import OutputLogclass Login(BaseFindEl):def __init__(self, devices):BaseFindEl.__init__(self, devices)def login(self, text="登录"):"""点击登录:param text::return:"""self.devices.implicitly_wait(3)try:btn = self.find_el_by_text(text=text)except NoSuchElementException:msg = "错误:没有找到{}控件".format(text)OutputLog.output_log().error(msg)else:OutputLog.output_log().debug("进入到登录界面")btn.click()def sign_in(self, text="注册"):""":param text: 注册:return:"""self.devices.implicitly_wait(3)try:btn = self.find_el_by_text(text=text)except NoSuchElementException:msg = "错误:没有找到{}控件".format(text)OutputLog.output_log().error(msg)else:OutputLog.output_log().debug("进入到注册界面")btn.click()def switch_to_username(self, text_contains="用微信号"):""":param text_contains: 切换到微信号/QQ号登录:return:"""try:btn = self.find_el_by_text(textContains=text_contains)except NoSuchElementException:msg = "错误:没有找到{}控件".format(text_contains)OutputLog.output_log().error(msg)else:OutputLog.output_log().debug("切换到微信号输入界面")btn.click()def user_edit(self, text_contains="请填写微信号"):"""寻找账号输入框:param text_contains::return: 账号阿输入edit"""try:username_edit = self.find_el_by_text(textContains=text_contains)except NoSuchElementException:msg = "错误:没有找到{}控件".format(text_contains)OutputLog.output_log().error(msg)else:OutputLog.output_log().debug("找到了账号输入编辑框")return username_editdef pwd_edit(self, text_contains="请填写密码"):"""寻找账号输入框:param text_contains::return: 账号阿输入edit"""try:pwd_edit = self.find_el_by_text(textContains=text_contains)except NoSuchElementException:msg = "错误:没有找到{}控件".format(text_contains)OutputLog.output_log().error(msg)else:OutputLog.output_log().debug("找到了账号输入编辑框")return pwd_editdef input_msg(self, user_name, pwd):"""输入信息:param user_name: 账号名称:param pwd: 密码:return:"""name_edit = self.user_edit()name_edit.clear()pwd_edit = self.pwd_edit()pwd_edit.clear()name_edit.send_keys(user_name)pwd_edit.send_keys(pwd)def find_toast(self, text="正在"):text_1 = "//*[contains(@text,'{}')]".format(text)toast = WebDriverWait(self.devices, 5, 0.00000001).until(lambda x: x.find_element_by_xpath(text_1))return toast.textdef login_fail(self, screenshots_nam):"""处理登录失败的弹窗:param screenshots_nam: 截图保存的名称:return:"""try:WebDriverWait(self.devices, 3).\until(lambda x: x.find_element_by_android_uiautomator('new UiSelector().textContains("密码错误")'))except TimeoutException:OutputLog.output_log().error("测试失败,没有找到登录失败的弹窗")file_name = 'screenshots/' + screenshots_nam + '.png'self.devices.get_screenshot_as_file(file_name)return 0else:OutputLog.output_log().debug("出现登录失败的弹窗")file_name = 'screenshots/' + screenshots_nam + '.png'self.devices.get_screenshot_as_file(file_name)self.find_el_by_text(text='确定').click()return 1def authorization_actions(self, screenshots_nam):try:WebDriverWait(self.devices, 3). \until(lambda x: x.find_element_by_android_uiautomator('new UiSelector().textMatches("(.*)权限申请")'))except TimeoutException:OutputLog.output_log().debug("没有出现权限申请弹窗")file_name = 'screenshots/' + screenshots_nam + '.png'self.devices.get_screenshot_as_file(file_name)else:OutputLog.output_log().debug("权限申请提示")file_name = 'screenshots/' + screenshots_nam + '.png'self.devices.get_screenshot_as_file(file_name)self.find_el_by_text(text='我知道了').click()def phone_authorization_actions(self, screenshots_nam, action='允许'):""":param screenshots_nam: 保存的截图:param action: 允许或者拒绝:return:"""try:WebDriverWait(self.devices, 4). \until(lambda x: x.find_element_by_android_uiautomator('new UiSelector().textMatches("(.*)电话权限")'))except TimeoutException:OutputLog.output_log().debug("没有出现电话权限申请弹窗")file_name = 'screenshots/' + screenshots_nam + '.png'self.devices.get_screenshot_as_file(file_name)else:OutputLog.output_log().debug("电话权限申请提示")file_name = 'screenshots/' + screenshots_nam + '.png'self.devices.get_screenshot_as_file(file_name)self.find_el_by_text(text=action).click()def sd_card_authorization_actions(self, screenshots_nam, action='允许'):""":param screenshots_nam: 保存的截图:param action: 允许或者拒绝:return:"""try:WebDriverWait(self.devices, 4). \until(lambda x: x.find_element_by_android_uiautomator('new UiSelector().textMatches("(.*)空间权限")'))except TimeoutException:OutputLog.output_log().debug("没有出现空间权限申请弹窗")file_name = 'screenshots/' + screenshots_nam + '.png'self.devices.get_screenshot_as_file(file_name)else:OutputLog.output_log().debug("空间权限申请提示")file_name = 'screenshots/' + screenshots_nam + '.png'self.devices.get_screenshot_as_file(file_name)self.find_el_by_text(text=action).click()

用例执行和报告输出

# 执行用例
# -*- coding:utf-8 -*-
# __author__ = "Cc"from InitDevices import InitDevices
from OutputLog import OutputLog
from read_msg import ReadData
from login import Loginimport unittest
import time
import os
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import TimeoutException
import HTMLReportclass LoginUnittest(unittest.TestCase):devices_object = Nonedevices = Nonedata = Noneindex0 = 0login_object = Nonedef __init__(self, *args, **kwargs):"""每个用例执行前,__init__都会执行一次"""super().__init__(*args, **kwargs)@classmethoddef setUpClass(cls):"""初始化设备,读取测试数据,获取一个测试对象:return:"""OutputLog.output_log().debug("==============开始测试,连接手机==============")cls.devices_object = InitDevices('devices.yaml', 'oppo_findx_pro')devices_info = cls.devices_object.read_devices()cls.devices = cls.devices_object.init_devices(devices_info)  # 返回设备对象OutputLog.output_log().debug("连接成功")  # 连接成功,开始操作cls.data = ReadData("login_msg.csv").read_data()  # 获取登录数据cls.index0 = 0cls.login_object = Login(cls.devices)@classmethoddef tearDownClass(cls):"""devices.quit():return:"""# OutputLog.output_log().debug("测试结束")# cls.devices.quit()f = os.popen(r"adb shell dumpsys activity top | findstr ACTIVITY", "r")  # 获取当前界面的Activitycurrent_activity = f.read()f.close()print(current_activity)  # cmd输出结果# 用in方法 判断一个字符串是否包含某字符appackage_name = 'com.ximalaya.ting.android'if appackage_name in current_activity:cls.drivers.quit()else:passdef setUp(self):"""每个用例执行前执行,这里切换登录方式:return:"""LoginUnittest.login_object.login()time.sleep(1)LoginUnittest.login_object.switch_to_username()def tearDown(self):"""每个用例执行后执行,os.system("adb shell pm clear com.tencent.mm"),执行成功返回0:return:"""time.sleep(1)if not os.system("adb shell pm clear com.tencent.mm"):# os.system("adb shell pm grant com.tencent.mm")OutputLog.output_log().debug("清除应用数据")LoginUnittest.index0 = LoginUnittest.index0 + 1time.sleep(3)# LoginUnittest.devices.start_activity('com.tencent.mm', '.ui.LauncherUI')os.system('adb shell am start com.tencent.mm/.ui.LauncherUI')else:OutputLog.output_log().debug("清除应用数据失败")time.sleep(2)# 测试登录失败def test_login_1(self):user_name = LoginUnittest.data[LoginUnittest.index0][0]pwd = LoginUnittest.data[LoginUnittest.index0][1]LoginUnittest.login_object.input_msg(user_name, pwd)msg = "登录信息" + user_name + pwdOutputLog.output_log().debug(msg)LoginUnittest.login_object.login()  # 登录# try:#     btn = WebDriverWait(LoginUnittest.devices, 7).\#         until(lambda x: x.find_element_by_android_uiautomator('new UiSelector().text("通讯录")'))# except TimeoutException:#     OutputLog.output_log().debug('登录失败')#     self.assertEqual(1, 1, '登录失败')file_name = "test_login_1" + "登录失败"result = LoginUnittest.login_object.login_fail(file_name)self.assertEqual(result, 1, '失败')def test_login_2(self):user_name = LoginUnittest.data[LoginUnittest.index0][0]pwd = LoginUnittest.data[LoginUnittest.index0][1]LoginUnittest.login_object.input_msg(user_name, pwd)msg = "登录信息" + user_name + pwdOutputLog.output_log().debug(msg)LoginUnittest.login_object.login()file_name_1 = 'test_login_2' + '权限申请提醒'LoginUnittest.login_object.authorization_actions(file_name_1)file_name_3 = 'test_login_2' + '存储权限申请提醒'LoginUnittest.login_object.phone_authorization_actions(file_name_3)file_name_2 = 'test_login_2' + '电话权限申请提醒'LoginUnittest.login_object.phone_authorization_actions(file_name_2)try:btn = WebDriverWait(LoginUnittest.devices, 7).\until(lambda x: x.find_element_by_android_uiautomator('new UiSelector().text("通讯录")'))except TimeoutException:OutputLog.output_log().debug('登录失败')else:self.assertEqual(btn.text, '通讯录', '测试成功')if __name__ == '__main__':test_suite = unittest.TestSuite()tests = [LoginUnittest('test_login_1'), LoginUnittest('test_login_2')]test_suite.addTests(tests)# runner = unittest.TextTestRunner()runner = HTMLReport.TestRunner(report_file_name="login_reports",output_path="login_report",title="登录功能测试报告",description="测试登录功能",thread_count=1,thread_start_wait=0,tries=0,delay=0,back_off=1,retry=False,sequential_execution=True,lang="cn")runner.run(test_suite)

执行结果

HTMLReport默认会输出一份.html报告文件和一份日志文件。只执行了两个用例,但是耗时0:2:28,代码还有待优化,Bat批处理命令执行,会不会对用例的执行效率有所提升呢?期待接下来的实践。
在这里插入图片描述
看完点赞 ~养成好习惯,以上内容希望对你有帮助,如果对软件测试、接口测试、自动化测试、面试经验交流感兴趣可以加入我们。642830685,免费领取最新软件测试大厂面试资料和Python自动化、接口、框架搭建学习资料!技术大牛解惑答疑,同行一起交流。

http://www.lbrq.cn/news/1082899.html

相关文章:

  • 自己做衣服网站/最新seo黑帽技术工具软件
  • 东莞做网站 信科网络/网站关键词优化排名
  • 如何拿模板做网站/seo基础篇
  • 潍坊网站建设公司有哪些内容/网络营销的方式都有哪些
  • 汕头网站设计哪家好/快速开发平台
  • 江阴网站建设推广/seo网站优化优化排名
  • 知识产权网站开发/优化服务平台
  • 网站开发代理报价表/网站制作公司有哪些
  • 亿万网站/百度电话人工服务
  • 网站做抢红包活动广告语/友情链接交换平台免费
  • 开放一个网站多少钱/爱站工具包
  • 办网站费用多少钱/中国免费网站服务器下载
  • 山东高端网站建设服务商/微信软文怎么写
  • 注册网站流程及资料/泰州网站优化公司
  • 叙述网站建设的流程/百度seo规则最新
  • 网站后台设计教程视频/优化设计五年级下册语文答案
  • 布吉网站建设哪家服务周到/种子搜索在线 引擎
  • 购物网站主页设计图/seo教程技术资源
  • 网站的seo优化方案/网站优化排名哪家性价比高
  • php学什么可以做网站/广州seo学徒
  • 哪家公司建设网站好/网页设计工资一般多少
  • wordpress 大气模板下载/域名查询seo
  • 网上手机网站建设计划书/刷网站软件
  • 东莞寮步镇疫情最新情况/图片优化软件
  • 人工智能搭建/武汉整站优化
  • 旅游开发公司网站建设方案书/在哪里可以找到网站
  • 济宁b2b网站开发公司/2024政治时政热点
  • 电脑记事本做网站/江阴百度推广公司
  • 临朐网站建设建站/网页广告怎么做
  • 网站动画效果用什么程序做的/网络推广方案
  • FFmpeg,如何插入SEI自定义数据
  • vue如何在data里使用this
  • TCPIP之常用协议
  • windows内核研究(异常-CPU异常记录)
  • LeetCode第350题_两个数组的交集II
  • 网安-中间件-Redis未授权访问漏洞