BasePage
import os
from datetime import datetime
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains, Chrome
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from common.logger_handler import logger
from config.path import img_path
class BasePage():
host = ""
def __init__(self, driver: Chrome):
self.driver = driver
self.size = driver.get_window_size()
self.height = self.size['height']
self.width = self.size['width']
def goto(self, url: str):
"""访问页面"""
if url.startswith('http'):
self.driver.get(url)
else:
url = self.host + url
self.driver.get(url)
logger.info(f"进入网页:{url}")
return self
def click_web(self, locator: tuple, force=False):
"""点击, 可以选择点击。"""
el = self.driver.find_element(*locator)
# 有时候,当元素不可点击的时候,使用 el.click 不生效
if not force:
self.driver.execute_script("arguments[0].click()", el)
else:
self.driver.execute_script("arguments[0].click({force: true})", el)
logger.info(f"元素被点击:{locator}")
return self
def click(self, locator):
"""点击原生app"""
el = self.driver.find_element(*locator)
el.click()
return self
def fill(self, locator, data):
"""输入内容"""
try:
el = self.driver.find_element(*locator)
el.send_keys(data)
logger.info(f"元素被输入内容:{locator}")
return self
except NoSuchElementException as e:
logger.error(f"元素无法定位{e}")
def get_attribute(self, locator, attr_name):
"""获取元素属性"""
elem = self.driver.find_element(*locator)
return elem.get_attribute(attr_name)
# el.name el.href
# 把方法变成属性,调用的时候可以不加括号
@property
def name(self, locator):
"""获取元素的name属性"""
return self.get_attribute(locator, 'name')
def double_click(self, locator):
"""双击"""
el = self.driver.find_element(*locator)
action = ActionChains(self.driver)
action.double_click(el).perform()
return self
# 鼠标拖动,鼠标悬停,
def drag_and_drop(self, start_locator, end_locator):
elem_start = self.driver.find_element(*start_locator)
elem_end = self.driver.find_element(*end_locator)
action = ActionChains(self.driver)
action.double_click(elem_start, elem_end).perform()
return self
def hover(self, locator):
"""鼠标悬停"""
el = self.driver.find_element(*locator)
action = ActionChains(self.driver)
action.move_to_element(el).perform()
return self
def wait_visible(self, locator, timeout=10, poll=0.2):
"""等待元素可见"""
wait = WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll)
el = wait.until(expected_conditions.visibility_of_element_located(locator))
return el
def wait_presence(self, locator, timeout=10, poll=0.2):
"""等待元素加载"""
wait = WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll)
el = wait.until(expected_conditions.presence_of_element_located(locator))
return el
def wait_clickable(self, locator, timeout=10, poll=0.2):
"""等待元素可以被点击"""
wait = WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll)
el = wait.until(expected_conditions.element_to_be_clickable(locator))
return el
def switch_to_frame(self, reference=None, timeout=10, poll=0.2):
"""iframe切换
reference:可以是frame 的name, id, element对象,索引, locator
"""
if not reference:
return self.driver.switch_to.default_content()
wait = WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll)
el = wait.until(expected_conditions.frame_to_be_available_and_switch_to_it(reference))
return el
# 窗口切换
def find_elements(self, locator):
return self.driver.find_elements(*locator)
def find_element(self, locator):
return self.driver.find_element(*locator)
def screenshot(self):
"""截图"""
# 获取现在的时间格式,2021-02-24-20-59-21
current_time = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
file_name = f'屏幕截图-{current_time}.png'
file_path = os.path.join(img_path, file_name)
self.driver.get_screenshot_as_file(file_path)
return self
def assert_equal(self, a, b):
assert a == b
def get_toast(self, text):
"""获取弹框"""
el = self.driver.find_element(By.XPATH, f'//*[contains(@text, "{text}")]')
return el
def swipe_left(self, offset=0.9):
"""封装 swipe"""
self.driver.swipe(start_x=self.width * offset,
start_y=self.height * 0.5,
end_x=self.width * (1 - offset),
end_y=self.height * 0.5)
def swipe_right(self, offset=0.9):
"""封装 swipe"""
self.driver.swipe(start_x=self.width * (1 - offset),
start_y=self.height * 0.5,
end_x=self.width * offset,
end_y=self.height * 0.5)
def swipe_up(self, offset=0.9):
self.driver.swipe(start_x=self.width * 0.5,
start_y=self.height * offset,
end_x=self.width * 0.5,
end_y=self.height * (1 - offset))
def swipe(self, direct='left', offset=0.9):
if direct == 'left':
return self.swipe_left(offset)
elif direct == 'right':
return self.swipe_right(offset)
elif direct == 'up':
return self.swipe_up(offset)
# def assert_equal(self, a, b):
# assert a == b
# if __name__ == '__main__':
# # 访问百度
# driver = Chrome()
# d = BasePage(driver)
# d.goto('http://www.baidu.com')
# # 搜索 “紧挨孤独”
# d.fill(('id', 'kw'), '紧挨孤独')
# d.click(('id', 'su'))
# import time
# time.sleep(3)
==============================================================
前置条件与前置登录
import pytest
from appium.webdriver import Remote
from selenium.webdriver.common.by import By
from common.basepage import BasePage
@pytest.fixture()
def driver():
"""启动和结束appium 对象"""
caps = {
'platformName': 'Android',
'automationName': 'Uiautomator2', # 必须要加才能定位 toast
'deviceName': 'emulator-5554',
'appPackage': 'com.lemon.lemonban',
'appActivity': 'com.lemon.lemonban.activity.WelcomeActivity',
'chromedriverExecutable': 'D:\chromedriver\chromedriver_242.exe',
'noReset': False
}
session = Remote(command_executor='http://127.0.0.1:4723/wd/hub',
desired_capabilities=caps)
session.implicitly_wait(10)
yield session
session.quit()
@pytest.fixture()
def login(driver):
"""登录的前置条件.
作为前置条件,可以通过偶 start_activity() 直接跳转
"""
page = BasePage(driver)
# 点击我的柠檬额
my_locator = (By.XPATH, '//*[@resource-id="com.lemon.lemonban:id/navigation_my"]')
page.click(my_locator)
# 点击我的头像
avatar_locator = (By.XPATH, '//*[@resource-id="com.lemon.lemonban:id/fragment_my_lemon_avatar_layout"]')
page.click(avatar_locator)
# 输入用户名
mobile_locator = (By.XPATH, '//*[@resource-id="com.lemon.lemonban:id/et_mobile"]')
page.fill(mobile_locator, '18173179913')
# 输入密码
password_locator = (By.XPATH, '//*[@resource-id="com.lemon.lemonban:id/et_password"]')
page.fill(password_locator, '179913')
# 点击登录
login_btn_locator = (By.XPATH, '//*[@resource-id="com.lemon.lemonban:id/content"]/android.widget.FrameLayout[1]')
page.click(login_btn_locator)
return driver
=========================================================
text模块的功能偏写
import time
from selenium.webdriver.common.by import By
from common.basepage import BasePage
def test_tiku(login):
"""测试步骤:
1、登录成功
2、点击题库按钮
3、点击 linux 题库
4、断言标题
5、获取第一道题的 title
6、滑动
7、获取后面题目的 title
8、断言: last_title - first_title = 滑动的次数
"""
# driver = login
basepage = BasePage(login)
# 点击题库按钮
tiku_locator = (By.XPATH, '//*[@resource-id="com.lemon.lemonban:id/navigation_tiku"]')
basepage.click( tiku_locator )
# 点击linux题库
detail_tiku_locator = (By.XPATH, '//*[@text="Linux"]')
basepage.click(detail_tiku_locator)
# 第一个断言,显示的文本是否是Linux
title_locator = (By.XPATH, '//*[@resource-id="com.lemon.lemonban:id/category_title"]')
actual = basepage.find_element( title_locator )
assert 'Linux' == actual.text.strip()
# 点击初级
level_locator = (By.XPATH, '//*[@resource-id="com.lemon.lemonban:id/first_level"]')
basepage.click(level_locator)
# 点击第一套题
first_tiku_locator = (By.XPATH, '//*[@text="Linux--初级--第1套"]')
basepage.click(first_tiku_locator)
# 第一个题的header
header_locator = (By.XPATH, '//*[@resource-id="com.lemon.lemonban:id/toolbar_textview"]')
title_first_elem = basepage.find_element(header_locator)
title_first = int(title_first_elem.text.split('/')[0])
# 滑动几次 5
for i in range(5):
basepage.swipe_left()
time.sleep(0.3)
# 获取后面的题
title_last_elem = basepage.find_element(header_locator)
title_last = int(title_last_elem.text.split('/')[0])
assert title_first + 5 == title_last
=======================================================================
本文介绍了一个基于Selenium的自动化测试框架实现,包括页面对象模型的设计、常用操作方法的封装,如点击、输入等,并通过具体示例展示了如何进行网站导航、元素定位及交互操作。
858

被折叠的 条评论
为什么被折叠?



