Selenium之-数据驱动框架

什么是数据驱动呢?就是,数据的改变从而驱动自动化测试的执行,最终引起测试结果的改变,也就是参数的应用化。

这里对于数据驱动测试,总结起来就是,数据驱动绝非读取文件(excel、csv、xml)中数据进行参数的赋值测试,因为采用的这种方式的测试,工作重心反而变成了如何读写文件,而对于自动化测试中关心的执行结果统计、断言结果反而不是那么容易去实现。尤其是测试页面结构发生大的调整时,文件类的字段调整获取也要发生较大的修改,所以文件数据驱动测试也是可以的,但是并不是最优解。

那么什么才是最优的数据驱动测试呢?是的,用单元测试 unittest 结合ddt库或者pytest结合@pytest.mark.parametrize。使用单元测试可以很方便的解决两个问题:

断言。利用单元测试的断言机制,我们可以方便的进行预期结果和实际结果的对比;
数据统计。执行完测试用例后,一共执行了多少条用例,执行成功多少,失败多少,失败的用例错误在哪里?单元测试框架会帮我们统计展示。

目录结构

# 目录结构
│  conftest.py
│  run.py
│  setting.py
│  test_login.py
│
├─common
│      __init__.py
│
├─data
│      login_data.py
│      __init__.py
│
├─pages
│  │  home_page.py
│  │  login_page.py
│  │  __init__.py
│  │
│  └─__pycache__
│          login_page.cpython-39.pyc
│          __init__.cpython-39.pyc
│
├─report
│      16ece934-b466-44f8-8027-adada24e33fc-container.json
│      1ad67988-183b-4a12-a221-c73c62dbe91a-container.json
│      259a4110-af52-49b9-8aaf-fe58c83412dc-container.json
└─

测试数据

login_data.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/1/21 20:58
# @Author  : shisuiyi
# @File    : login_data.py
# @Software: win10 Tensorflow1.13.1 python3.9
data_error = [['123', 'abc', '密码有效长度是6到30个字符'],
              ['123', '12345678', '用户名或密码无效'],
              ['188****463', '1234568', '密码错误']]

data_success = [('188****63', '*****205f', '师语'), ]

page类

登录页:login_page.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/1/20 20:34
# @Author  : shisuiyi
# @File    : login_page.py
# @Software: win10 Tensorflow1.13.1 python3.9
from selenium.webdriver.common.by import By

import setting


class LoginPage:
    """登录页面"""
    url = setting.host + '/User/login.html'

    def __init__(self, driver):
        self.driver = driver

    def reload(self):
        """刷新"""
        self.driver.refresh()

    def load(self):
        self.driver.get(self.url)

    def login(self, *args):
        """登录"""
        # 输入用户户名
        self.driver.find_element(By.XPATH, '//input[@name="account"]').send_keys(args[0])

        # 输入密码
        self.driver.find_element(By.XPATH, '//input[@name="pass"]').send_keys(args[1])

        # 点击登录
        self.driver.find_element(By.XPATH, '//a[@class="btn-btn" and text()="登录"]').click()

    def logout(self):
        """退出登录"""
        pass

    def forget_password(self):
        """忘记密码"""
        pass

    def get_error_msg(self):
        """获取登录失败的错误信息"""
        return self.driver.find_element(By.XPATH, '//p[@class="error-tips"]').text

首页:home_page.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/1/21 20:43
# @Author  : shisuiyi
# @File    : home_page.py
# @Software: win10 Tensorflow1.13.1 python3.9


from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait


class HomePage:
    def __init__(self, driver):
        self.driver = driver

    def get_username(self):
        """获取用户名称"""
        wait = WebDriverWait(self.driver, timeout=8)
        mark = ('xpath', "//img[@class='avatar']")
        when = expected_conditions.presence_of_element_located(mark)
        el = wait.until(when)
        actual = el.get_attribute('alt')
        return actual

脚手架conftest

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/1/15 14:14
# @Author  : shisuiyi
# @File    : conftest.py
# @Software: win10 Tensorflow1.13.1 python3.9
import pytest
from selenium import webdriver


def pytest_collection_modifyitems(items):
    """
    测试用例收集完成时,将收集到的item的name和nodeid的中文显示在控制台上,
    为解决使用 pytest.mark.parametrize 参数化的时候,加 ids 参数用例描述有中文时,
    在控制台输出会显示unicode编码,中文不能正常显示。

    :return:
    """
    for item in items:
        item.name = item.name.encode("utf-8").decode("unicode_escape")
        print(item.nodeid)
        item._nodeid = item.nodeid.encode("utf-8").decode("unicode_escape")


@pytest.fixture(scope='session')
def driver():
    # 养成设置隐性
    driver = webdriver.Chrome()
    driver.implicitly_wait(8)
    driver.maximize_window()
    yield driver
    driver.quit()

测试用例

test_login.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/1/13 19:46
# @Author  : shisuiyi
# @File    : test_login.py
# @Software: win10 Tensorflow1.13.1 python3.9
import pytest

from data.login_data import data_error, data_success
from pages.login_page import LoginPage
from pages.home_page import HomePage


class TestLogin(object):
    """测试登录功能"""

    @pytest.mark.parametrize('username,password,expected', data_error, ids=['密码过短', '用户名或密码无效', '密码错误'])
    def test_login_error(self, username, password, expected, driver):
        login_page = LoginPage(driver)
        login_page.load()
        login_page.login(username, password)
        actual = login_page.get_error_msg()
        assert expected in actual

    @pytest.mark.parametrize('username,password,expected', data_success, ids=['登录成功'])
    def test_login_success(self, username, password, expected, driver):
        login_page = LoginPage(driver)
        login_page.load()
        login_page.login(username, password)
        actual = HomePage(driver).get_username()
        assert expected == actual

测试结果

============================= test session starts =============================
collecting ... test_login.py::TestLogin::test_login_error[\u5bc6\u7801\u8fc7\u77ed]
test_login.py::TestLogin::test_login_error[\u7528\u6237\u540d\u6216\u5bc6\u7801\u65e0\u6548]
test_login.py::TestLogin::test_login_error[\u5bc6\u7801\u9519\u8bef]
test_login.py::TestLogin::test_login_success[\u767b\u5f55\u6210\u529f]
collected 4 items

test_login.py::TestLogin::test_login_error[密码过短] 
test_login.py::TestLogin::test_login_error[用户名或密码无效] 
test_login.py::TestLogin::test_login_error[密码错误] 
test_login.py::TestLogin::test_login_success[登录成功] 

============================== 4 passed in 8.81s ==============================

Process finished with exit code 0
PASSED              [ 25%]PASSED      [ 50%]PASSED              [ 75%]PASSED            [100%]