app实战项目

本文介绍了一个基于Selenium的自动化测试框架实现,包括页面对象模型的设计、常用操作方法的封装,如点击、输入等,并通过具体示例展示了如何进行网站导航、元素定位及交互操作。

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


=======================================================================

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值