App自动化
Appium 基础
安装 APK并打开
import time
from appium.webdriver import Remote
# apk 的路径
file = r'apk路径'
caps = {"platformName": "Android",
"deviceName": "设备号", # 可通过 adb devices 或者 adb get-serialno 获取
"app": file}
driver=Remote(command_executor='http://127.0.0.1:4723/wd/hub',desired_capabilities=caps) # 4723要与Appium客户端的端口号对应,4723为默认值
time.sleep(3)
driver.quit()
启动 APK
'''
获取apk包名
adb shell dumpsys activity activities | find "mFocusedActivity"
aapt dumpsys badging 电脑端apk路径 通过应用查看包名(配置aapt环境变量,或在aapt.exe路径下运行)
adb logcat | findStr -i displayed
adb shell pm list package -s 查询系统apk包名
adb shell pm list package -3 查询第三方apk包名
adb shell am monitor 查看将要启动或退出app的包名
adb shell dumpsys window windows | findstr mFocusedApp 查看当前界面的app的包名
adb shell dumpsys activity top | find "ACTIVITY" 查看启动的app的包名
adb shell dumpsys activity activities | findstr "Run" 查看所有启动的应用的包名
adb shell dumpsys window w |findstr \/ |findstr name= 查看当前启动应用的包名
'''
import time
from appium.webdriver import Remote
caps = {"platformName": "Android",
"deviceName": "设备号",
"appPackage": "包名",
"appActivity": ".guide.SplashActivity",
"noReset": True} # 清除应用缓存数据,比如避免app进行初始化操作
driver = Remote(command_executor='http://127.0.0.1:4723/wd/hub', desired_capabilities=caps)
size = driver.get_window_size() # 获取屏幕像素 {'width': 2160, 'height': 3840}
time.sleep(2)
driver.quit()
查找元素
import time
from appium.webdriver import Remote
caps = {
"platformName": "Android",
"deviceName": "设备名",
"appPackage": "包名",
"appActivity": ".guide.SplashActivity",
"noReset": True,
# "unicodeKeyboard": True, # 启用Unicode输入法,设置为true可以输入中文字符,默认为false
# "resetKeyboard": True
}
driver = Remote(command_executor='http://127.0.0.1:4723/wd/hub', desired_capabilities=caps)
# 隐性等待
driver.implicitly_wait(10)
# 找元素
# xpath定位://class[@属性="值"]
xpath = "//android.widget.ImageView[@resource-id='com.qiduo.mail:id/titlebar_right_btn' and @index='1']"
el = driver.find_element("xpath", xpath)
# el = driver.find_element("class name","android.widget.ImageView")
print(el)
print(el.text) # 打印文本
print(el.location) # 获取元素在屏幕上的坐标
print(el.rect) # 获取元素在屏幕上的坐标及长宽
print(el.get_attribute('class')) # 获取元素的某属性的值
el.click()
driver.find_element("id", "com.qiduo.mail:id/email_addr_input").send_keys("哈哈") # 输入
driver.find_element("id", "com.qiduo.mail:id/receive_server_login_name_input").clear() # 清空文本框数据
checked_el = driver.find_element("id", "com.qiduo.mail:id/receive_server_encryption_checkbox")
if checked_el.get_attribute("checked") == "true":
checked_el.click()
"""
定位方式:
通过 id 定位 resource-id 的值
通过 class name 定位 class 的值
通过 accessibility id 定位 content-desc 的值
"""
# 获取元素 text 属性值
print(driver.find_element("id", "com.qiduo.mail:id/receive_server_addr_label").text)
print(driver.find_element("id", "com.qiduo.mail:id/receive_server_addr_label").get_attribute("text"))
# 获取 content-desc 属性,如果 content-desc 属性为空,那么获取的就是 text 属性
print(driver.find_element("id", "com.qiduo.mail:id/receive_server_addr_label").get_attribute("name"))
# 获取元素 class 属性值
print(driver.find_element("id", "com.qiduo.mail:id/receive_server_addr_label").get_attribute("class"))
print(driver.find_element("id", "com.qiduo.mail:id/receive_server_addr_label").get_attribute("className"))
# 获取元素 id 属性值
print(driver.find_element("id", "com.qiduo.mail:id/receive_server_addr_label").get_attribute("resourceId"))
time.sleep(3)
driver.quit()
输入中文,目前不加下面两个参数也是可以添加中文的
caps["unicodeKeyboard"] = True
caps["resetKeyboard"] = True
显性等待
import time
from appium.webdriver import Remote
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
caps = {"platformName": "Android",
"deviceName": "设备号",
"appPackage": "包名",
"appActivity": ".activity.MainActivity",
"noReset": True}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
xpath = '//android.widget.ImageView[@resource-id="com.qiduo.mail:id/titlebar_toggle_slidingmenu_btn"]'
# 显性等待
locator = ("xpath", xpath)
wait = WebDriverWait(driver, timeout=8)
wait.until(expected_conditions.presence_of_element_located(locator))
el = driver.find_element("xpath", xpath)
print(el.text)
print(el.rect)
el.click()
time.sleep(3)
driver.quit()
打开 APP 指定到的活动页面
import time
from appium.webdriver import Remote
caps = {"platformName": "Android",
"deviceName": "设备号",
"appPackage": "包名",
"appActivity": ".activity2.MainActivity",
"noReset": True}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
driver.implicitly_wait(10)
# driver.start_activity("包名", "活动页面名称")
driver.start_activity("包名", ".activity2.LoginActivity") # 打开app指定到的活动页面
# send_keys
driver.find_element("id","定位元素1").send_keys("123456") # 账号
driver.find_element("id","定位元素2").send_keys("abcdef") #密码
driver.find_element("id","定位元素3").click() # 登录
time.sleep(3)
driver.quit()
后台执行
import time
from appium.webdriver import Remote
caps = {"platformName": "Android",
"deviceName": "设备号",
"appPackage": "包名",
"appActivity": ".activity2.MainActivity",
"noReset": True}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
time.sleep(1)
driver.background_app(5) # 放到后台执行 driver.background_app(后台执行时间)
time.sleep(3)
driver.activate_app("com.android.settings") # 激活app,将app放到前台执行
time.sleep(3)
driver.quit()
等待activity出现
import time
from appium.webdriver import Remote
caps = {"platformName": "Android",
"deviceName": "127.0.0.1:62001",
"appPackage": "包名",
"appActivity": "引导页名称",
"noReset": True}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
driver.implicitly_wait(10)
driver.find_element("id", "com.lemon.lemonban:id/navigation_tiku").click()
print(driver.current_activity) # 获取当前界面的activity
driver.wait_activity("等待的引导页名称", 5)
driver.find_element("xpath", "//android.widget.TextView[@text='text文本值']").click()
driver.wait_activity("等待的引导页名称", 5)
assert driver.find_element("xpath", "//android.widget.TextView[@text='text文本值']").get_attribute("text") == "text文本值"
time.sleep(3)
driver.quit()
滑动
| 滑动方法名称 | 实现方式 | 是否有惯性 |
|---|---|---|
| swipe | 传入坐标滑动 | 有惯性(当持续时间足够长时,实现的效果和drag_and_drop一致) |
| scroll | 传入元素滑动 | 有惯性 |
| drag_and_drop | 传入元素滑动 | 无惯性 |
swipe滑动
import time
from appium.webdriver import Remote
caps = {"platformName": "Android",
"deviceName": "设备号",
"appPackage": "包名",
"appActivity": ".activity2.MainActivity"}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
time.sleep(2)
# 获取屏幕尺寸
size = driver.get_window_size()
print(size)
width = size["width"]
height = size["height"]
# 从右往左滑动 driver.swipe(起始点x坐标, 起始点y坐标, 结束点x坐标, 结束点y坐标, 滑动的时间间隔(可以省略))
driver.swipe(width * 0.9, height * 0.5, width * 0.1, height * 0.5, 1000)
driver.implicitly_wait(10)
driver.find_element("id", "定位元素1").click()
driver.find_element("id", "定位元素2").click()
time.sleep(3)
driver.quit()
scroll滑动
import time
from appium.webdriver import Remote
caps = {"platformName": "Android",
"deviceName": "设备号",
"appPackage": "com.android.settings",
"appActivity": ".Settings",
"noReset": True}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
driver.implicitly_wait(10)
time.sleep(1)
origin_el = driver.find_element("xpath", "//android.widget.TextView[@text='电池']")
destination_el = driver.find_element("xpath", "//android.widget.TextView[@text='蓝牙']")
driver.scroll(origin_el, destination_el, 1000) # 从电池的位置滑到蓝牙的位置
time.sleep(3)
driver.quit()
drag_and_drop滑动
import time
from appium.webdriver import Remote
caps = {"platformName": "Android",
"deviceName": "emulator-5554",
"appPackage": "com.android.settings",
"appActivity": ".Settings",
"noReset": True}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
driver.implicitly_wait(10)
time.sleep(1)
origin_el = driver.find_element("xpath", "//android.widget.TextView[@text='电池']")
destination_el = driver.find_element("xpath", "//android.widget.TextView[@text='蓝牙']")
driver.drag_and_drop(origin_el, destination_el)
time.sleep(3)
driver.quit()
按键操作
import time
from appium.webdriver import Remote
class Key(object):
"""对按键进行封装"""
enter = 66
home = 3
volume_up = 24
volume_down = 25
def press_enter(driver):
"""对 enter 键进行单独的封装"""
driver.press_keycode(Key.enter)
def press_home(driver):
"""对 home 键进行单独的封装"""
driver.press_keycode(Key.home)
caps = {"platformName": "Android",
"deviceName": "设备号",
"appPackage": "包名",
"appActivity": ".activity2.MainActivity",
"noReset": True}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
# 音量+
time.sleep(3)
driver.press_keycode(Key.volume_up) # 音量+键
time.sleep(2)
# 按下home进一步的封装
press_home(driver)
time.sleep(2)
driver.quit()
tap模拟手势点击
import time
from appium.webdriver import Remote
caps = {"platformName": "Android",
"deviceName": "设备号",
"appPackage": "包名",
"appActivity": "activity名称",
"noReset": True}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
driver.implicitly_wait(10)
driver.wait_activity(".activity.MainActivity", 10)
driver.tap([(1000, 3775)], 500) # 下下策(更换手机后屏幕分辨率也改变,坐标需要改变) # 模拟手势点击,最多支持五个点
# driver.tap([(743, 3660), (1416, 3840)], 500)
driver.wait_activity(".activity.DifficultyLevelActivity", 5)
el = driver.find_element("xpath", "//android.widget.TextView[@text='软件']")
assert el.text == "软件"
time.sleep(3)
driver.quit()
tap多点触控(目前测试一直报错,不知道为什么)
# 不能执行perform(),不知道为啥
import time
from appium.webdriver import Remote
from appium.webdriver.common.multi_action import MultiAction
from appium.webdriver.common.touch_action import TouchAction
caps = {"platformName": "Android",
"deviceName": "设备号",
"appPackage": "包名",
"appActivity": "activity名称",
"noReset": True}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
driver.implicitly_wait(10)
driver.wait_activity(".activity.MainActivity", 10)
el1 = driver.find_element("xpath", "//*[@text='报名']")
el2 = driver.find_element("xpath", "//*[@text='社区']")
action1 = TouchAction(driver).tap(el1)
action2 = TouchAction(driver).tap(el2)
MultiAction(driver).add(action1,action2).perform() # 不知道为什么显示“找不到.perform()”
time.sleep(3)
driver.quit()
long_press长按
import time
from appium.webdriver import Remote
from appium.webdriver.common.touch_action import TouchAction
caps = {"platformName": "Android",
"deviceName": "设备号",
"appPackage": "包名",
"appActivity": ".activity2.MainActivity",
"noReset": True}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
driver.implicitly_wait(10)
driver.wait_activity(".activity2.MainActivity", 10)
el = driver.find_element("id","id元素值")
TouchAction(driver).long_press(el=el,duration=5000).perform() # 长按5秒
driver.find_element("id","com.youdao.note:id/btn_cancel").click()
time.sleep(3)
driver.quit()
手机 toast 弹窗处理
import time
from appium.webdriver import Remote
caps = {"platformName": "Android",
"deviceName": "设备号",
"appPackage": "包名",
"appActivity": ".activity2.MainActivity",
"automationName": "UiAutomator2", # 识别手机Toast加上这个键值对
"noReset": True}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
driver.implicitly_wait(10)
time.sleep(3)
driver.start_activity("包名", ".activity2.LoginActivity")
driver.find_element("id", "元素").click() # 登录
# 定位 toast
toast = driver.find_element("xpath", "//android.widget.Toast") # 固定语法
# toast = driver.find_element("xpath", "//*[contains(@text, '用户名和密码不能为空')]") # 通过toast文本定位
print(toast.text)
time.sleep(3)
driver.quit()
webview 处理(H5页面)
-
class 中,存在
android.webkit.WebView需要用 webview 来处理
-
谷歌浏览器访问
chrome://inspect确认手机 webview 版本,下载chromedriver.exe驱动
-
webview 中的元素可以通过
UC 开发者工具定位,在设置中选择本地 Devtools Inspector UI 资源,在'Home'中点击inspect即可查看
import time
from appium.webdriver import Remote
caps = {"platformName": "Android",
"chromedriverExecutableDir": r"D:\code\appium_record", # 驱动位置
"deviceName": "设备号",
"appPackage": "包名",
"appActivity": ".activity.MainActivity"}
driver = Remote(command_executor="http://127.0.0.1:4723/wd/hub", desired_capabilities=caps)
driver.implicitly_wait(10)
# 点击 师资团队 进入web页面
driver.find_element("xpath", "//*[@text='text的文本信息']").click()
time.sleep(5)
# 打印所有的上下文
print(driver.contexts)
# 上下文切换
driver.switch_to.context(driver.contexts[-1])
# driver.switch_to.context('WEBVIEW的名称')
# 注意:有时候一个页面会包含多个标签
print(driver.window_handles)
# 点击查看全部
driver.find_element("xpath", "//*[@id='__impage-component-wrapper-1']/section/div[1]/div/span/span").click()
time.sleep(3)
driver.quit()
封装
Appium运行原理
- 自动化脚本向AppiumServer发送注册参数(URL,platformName, platformVersion,deviceName,appPackage,appActivity)
- AppiumServer将bootstrap.jar包放入手机端中
- 手机端用bootstrap启动手机端口(4723),并将端口返回给AppiumServer(相当于建立好了通信连接)
- 自动化脚本发送请求(操作或命令或动作)给AppiumServer
- AppiumServer将请求解析并发送给bootstrap
- bootstrap将请求解析发给UIAutomator
- UIAutomator执行相应的操作并将结果返回给bootstrap
- bootstrap将响应结果返回给AppiumServer
- AppiumServer将响应结果返回到脚本
结构
python + appium + log +openpyxl
PO模式
conftest.py夹具
import pytest
from appium_record.appium_practice_v4.pages.homepage import HomePage
from appium_record.appium_practice_v4.pages.tiku_page import TikuPage
from appium_record.appium_practice_v4.pages.tiku_page import CollectPage
from appium_record.appium_practice_v4.pages.userpage import UserPage
from appium_record.appium_practice_v4.common.logging_processing import logger
from appium_record.appium_practice_v4.common.excel import read_excel
from appium_record.appium_practice_v4.setting.path import path
case_datas_success = read_excel(path(r"data/cases.xlsx"), "login_success")
print(case_datas_success)
@pytest.fixture()
def driver():
caps = {"platformName": "Android",
"deviceName": "设备名称",
"appPackage": "包名",
"appActivity": "活动页名称"}
d = Remote(command_executor='http://127.0.0.1:4723/wd/hub', desired_capabilities=caps)
logger.info("成功打开app")
d.implicitly_wait(10)
yield d
time.sleep(5)
d.quit()
logger.info("退出app")
@pytest.fixture(params=case_datas_success)
def login_params(request):
return request.param
@pytest.fixture()
def login(driver, login_params):
"""登录功能"""
HomePage(driver).enter_user()
UserPage(driver).login(login_params["mobile"], login_params["passwd"])
@pytest.fixture()
def user_page(driver):
return UserPage(driver)
@pytest.fixture()
def tiku_page(driver):
return TikuPage(driver)
@pytest.fixture()
def collect_page(driver):
return CollectPage(driver)
@pytest.fixture()
def home_page(driver):
return HomePage(driver)
run.py:自动化运行入口
import pytest
import time
# import traceback
from appium_record.appium_practice_v4.common.logging_processing import logger
time_cur = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())
try:
logger.info("开始运行自动化")
pytest.main(["-s", r"--html=report/report_" + time_cur + ".html", '--capture=sys', '--disable-warnings'])
# pytest.main(["tests/test_collect.py","-s", r"--html=report/report_" + time_cur + ".html",'--capture=sys','--disable-warnings'])
# pytest.main(["-s", r"--html=report/report_" + time_cur + ".html",'--capture=sys','--disable-warnings','--log-cli-level=INFO'])
# pytest.main(["-s"])
except Exception as e:
logger.info(e)
# logger.info(traceback.print_exc())
# pytest.main(["-s"])
common文件夹
basepage.py:封装常见的操作
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from appium_record.appium_practice_v4.common.logging_processing import logger
class Key(object):
enter = 66
home = 3
volume_up = 24
volume_down = 25
class BasePage:
def __init__(self, driver):
self.driver = driver
def get_element(self, locator):
"""找元素 ("id", "")"""
return self.driver.find_element(*locator)
def wait_element_clickable(self, locator, timeout=10):
"""等待某个元素可以被点击"""
wait = WebDriverWait(self.driver, timeout=timeout)
return wait.until(expected_conditions.element_to_be_clickable(locator))
def wait_element_visible(self, locator, timeout=10):
"""等待某个元素可见"""
wait = WebDriverWait(self.driver, timeout=timeout)
return wait.until(expected_conditions.visibility_of_element_located(locator))
def click(self, locator):
"""点击某个元素"""
# el = self.wait_element_clickable(locator)
el = self.get_element(locator)
el.click()
def send_keys(self, locator, keyword):
# el = self.wait_element_visible(locator)
el = self.get_element(locator)
el.send_keys(keyword)
def swipe_down(self):
"""从上到下的滑动"""
size = self.driver.get_window_size()
print(size)
width = size["width"]
height = size["height"]
self.driver.swipe(start_x=width * 0.5, start_y=height * 0.1, end_x=width * 0.5, end_y=height * 0.9)
def swipe_up(self):
"""从下到上的滑动"""
size = self.driver.get_window_size()
print(size)
width = size["width"]
height = size["height"]
self.driver.swipe(start_x=width * 0.5, start_y=height * 0.9, end_x=width * 0.5, end_y=height * 0.1)
def swipe_left(self):
"""从右到左的滑动"""
size = self.driver.get_window_size()
width = size["width"]
height = size["height"]
try:
self.driver.swipe(start_x=width * 0.9, start_y=height * 0.5, end_x=width * 0.1, end_y=height * 0.5, duration=1000)
except Exception as e:
logger.info(e)
def swipe_right(self):
"""从左到右的滑动"""
size = self.driver.get_window_size()
width = size["width"]
height = size["height"]
self.driver.swipe(start_x=width * 0.1, start_y=height * 0.5, end_x=width * 0.1, end_y=height * 0.9)
def press_keycode(self, key):
"""self.press_keycode(Key.enter)"""
self.driver.press_keycode(key)
def press_enter(self):
"""按回车 self.press_enter()"""
self.driver.press_keycode(Key.enter)
def get_toast_text(self):
"""获取 toast 文本"""
el = self.get_element(("xpath", "//android.widget.Toast"))
return el.text
excel.py:读取excel表格
import openpyxl
def read_excel(excel_path, sheet_name):
workbook = openpyxl.load_workbook(excel_path)
sheet_name = workbook[sheet_name]
items = list(sheet_name.values)
title = items[0]
new_items = [dict(zip(title, item)) for item in items[1:]]
return new_items
logging_processing.py封装日志,包括日志在控制台和文件上的文件
import logging
import datetime
import os
from logging.handlers import RotatingFileHandler
from appium_record.appium_practice_v4.setting.path import path
if not os.path.exists(path("log")):
os.mkdir(path("log"))
print("创建log文件夹成功")
log_path = path("log")
data = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S_%p")
class Logging():
def __init__(self):
self.logger = logging.getLogger('日志处理')
self.logger.setLevel(logging.INFO)
self.log_formatter = logging.Formatter(
fmt="%(asctime)s,%(msecs)03d - %(levelname)s - [%(filename)s] - %(funcName)s - [line: %(lineno)d] - %(message)s",
datefmt="%Y-%m-%d %p %H:%M:%S")
def __create_console_handler(self):
# self.console_handler = logging.handlers.TimedRotatingFileHandler('all.log', when='midnight', interval=1, backupCount=7, atTime=datetime.time(0, 0, 0, 0))
self.console_handler = logging.StreamHandler() # 默认是sys.stderr
self.console_handler.setLevel(logging.DEBUG)
self.console_handler.setFormatter(self.log_formatter)
return self.console_handler
def __create_file_handler(self):
self.file_handler = logging.FileHandler(log_path / 'logs.log', encoding="utf-8")
# self.file_handler = RotatingFileHandler(filename=log_path / f"log_{data}.log", mode="a", maxBytes=5 * 1024 * 1024, backupCount=5, encoding='utf-8')
self.file_handler.setLevel(logging.INFO)
self.file_handler.setFormatter(self.log_formatter)
return self.file_handler
def add_handler(self):
self.__create_console_handler()
self.__create_file_handler()
if not self.logger.handlers:
self.logger.addHandler(self.console_handler)
self.logger.addHandler(self.file_handler)
return self.logger
logger = Logging().add_handler()
cases存放测试用例

pages文件夹:存档坐标和页面的操作
from appium_record.appium_practice_v4.common.basepage import BasePage
from appium_record.appium_practice_v4.common.logging_processing import logger
class UserPage(BasePage):
avator_locator = ("id", "元素")
mobile_locator = ("id", "元素")
password_locator = ("id", "元素")
login_confirm_locator = ("id", "元素")
# Toast 弹框
toast_locator = ("xpath", "//android.widget.Toast")
username_locator = ("id", "元素")
tiku_locator = ("id", "元素")
def login(self, mobile_phone, password):
self.click(self.avator_locator)
logger.info("点击头像登录")
if mobile_phone:
self.send_keys(self.mobile_locator, mobile_phone)
logger.info(f"输入账号'{mobile_phone}'")
if password:
self.send_keys(self.password_locator, password)
logger.info(f"输入密码'{password}'")
self.click(self.login_confirm_locator)
logger.info("点击'登录'")
def get_error_msg(self):
"""获取登录失败的错误信息"""
toast = self.get_element(self.toast_locator)
logger.info(f"toast信息为'{toast.text}'")
return toast.text
def get_username(self):
"""获取用户昵称"""
el = self.get_element(self.username_locator)
logger.info(f"用户昵称为'{el.text}'")
return el.text
def enter_tiku(self):
self.click(self.tiku_locator)
setting:存放配置信息
from pathlib import Path
def path(path):
project_path = Path(__file__).absolute().parent.parent
return project_path / path
tests文件夹:存放测试用例
import pytest
from pages.homepage import HomePage
from appium_record.appium_practice_v4.pages.userpage import UserPage
from appium_record.appium_practice_v4.common.logging_processing import logger
from appium_record.appium_practice_v4.common.excel import read_excel
from appium_record.appium_practice_v4.setting.path import path
"""
数据驱动测试(ddt) data driven testing.
多组数据, 测试逻辑,测试步骤
"""
# case_data = [dict(mobile_phone="123", password="456", expected="手机号码格式不正确"),
# dict(mobile_phone="", password="", expected="手机号码或密码不能为空")]
case_datas = read_excel(path(r"data/cases.xlsx"),"login_fail")
# case_data_success = [dict(mobile_phone="正确的手机号", password="正确的密码", expected="期望值")]
case_datas_success = read_excel(path(r"data/cases.xlsx"),"login_success")
class TestLogin():
@pytest.mark.parametrize("case_data", case_datas)
def test_login(self, driver, case_data):
HomePage(driver).enter_user()
user_page = UserPage(driver)
mobile_phone = case_data.get("mobile")
password = case_data.get("passwd")
expected = case_data.get("expected")
# user_page.login(case_info["mobile_phone"], case_info["password"])
user_page.login(mobile_phone, password)
actual = user_page.get_error_msg()
# assert actual == case_info["expected"]
assert actual == expected
logger.info("----------------PASS----------------")
@pytest.mark.parametrize("case_info", case_datas_success)
def test_login_success(self, driver, case_info):
HomePage(driver).enter_user()
mobile_phone = case_info.get("mobile")
password = case_info.get("passwd")
expected = case_info.get("expected")
UserPage(driver).login(mobile_phone, password)
actual = UserPage(driver).get_username()
assert actual == expected
logger.info("----------------PASS----------------")

浙公网安备 33010602011771号