https://blog.csdn.net/weixin_45912307/article/details/108955085

一、项目环境准备工作

1.配置虚拟环境, 请参考之前一篇文章:https://blog.csdn.net/weixin_45912307/article/details/108347547

2. 创建项目虚拟环境
mkvirtualenv -p python3 虚拟环境名称
在这里插入图片描述

二、 创建项目(以pycharm为例)

1. 点击 new project
在这里插入图片描述
2. 先找到刚刚创建好的虚拟环境目录
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 创建工程目录
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
4. 选择好虚拟环境,选择好工程目录,点击创建
在这里插入图片描述
5. 创建好的工程目录架构
在这里插入图片描述

三、框架的封装

1. 创建框架目录

在这里插入图片描述
最终框架结构如图:
在这里插入图片描述

2. 公共层

2.1 base_page.py 页面公共函数

# —— coding :utf-8 ——
# @time:    2020/10/7 20:58
# @IDE:     webTest_frmewok_v2.0
# @Author:  jsonLiu
# @Email:   xxxxxxx@qq.com
# @File:    base_page.py
import logging
import datetime

from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys

from Common.file_path import screenshots_path
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import win32gui
import win32con
# pip install pywin32

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

    # 1. 等待元素可见
    def wait_eleVisible(self, locator, timeout=20, poll_frequency=0.5, doc=""):
        """
        :param locator: 元素定位,元组形式。 (元素类型,元素定位方式)
        :param timeout:
        :param poll_frequency:
        :param doc: 模块名称_页面名称_操作名称
        :return:
        """
        logging.info('等待元素可见:{}可见'.format(locator))
        try:
            # 开始等待时间
            start_time = datetime.datetime.now()
            WebDriverWait(self.driver, timeout, poll_frequency).until(EC.visibility_of_element_located(locator))
            # 结束等待时间
            end_time = datetime.datetime.now()
            # 等待时长,转换为s
            wait_times = (end_time - start_time).seconds
            logging.info(
                "{0}:元素:{1}已可见,等待起始时间:{2},等待结束时间:{3},等待时间:{4}".format(doc, locator, start_time, end_time, wait_times))
        except:
            # 铺获异常到日志中
            # 截图--保存到指定目录
            logging.exception('等待元素可见失败!')
            self.save_screenshot(doc)
            raise

    # 2. 判断元素是否存在
    def ele_isExist(self, locator, timeout=10, doc=""):
        logging.info("{}中是否存在元素:{}".format(doc, locator))
        try:
            WebDriverWait(self.driver, timeout).until(EC.visibility_of_element_located(locator))
            logging.info("{0}秒内页面{1}存在中存在元素:{2}".format(timeout, doc, locator))
            return True
        except:
            logging.exception("{0}秒内页面{1}存在中不存在元素:{2}".format(timeout, doc, locator))
            return False

    # 3. 查找元素
    def find_element(self, locator, doc=""):
        logging.info('{0}查找元素:{1}'.format(doc, locator))
        try:
            return self.driver.find_element(*locator)
        except:
            logging.exception('查找元素失败')
            self.save_screenshot(doc)
            raise
            # 3. 判断元素是否存在

    # 4. 点击操作
    def click_element(self, locator, doc):
        ele = self.find_element(locator, doc)
        logging.info('{0}点击元素:{1}'.format(doc, locator))
        try:
            ele.click()
            logging.info('{0}点击元素:{1}成功'.format(doc, locator))
        except:
            logging.exception('元素点击操作失败!')
            self.save_screenshot(doc)
            raise

    # 5. 输入操作
    def input_text(self, locator, content, doc=""):
        ele = self.find_element(locator, doc)
        logging.info('{0}元素:{1}输入文本'.format(doc, locator))
        try:
            logging.info('{0}元素:{1},输入内容为:{2}'.format(doc, locator, content))
            ele.send_keys(content)
        except:
            logging.exception('{0}元素:{1}输入失败'.format(doc, locator))
            self.save_screenshot(doc)
            raise

    # 6. 获取元素文本
    def get_element_text(self, locator, text, doc=""):
        ele = self.find_element(locator, doc)
        logging.info('{0}获取元素:{1}的文本内容'.format(doc, locator))
        try:
            text = ele.text
            logging.info('{0}获取元素:{1}的文本内容为:{2}'.format(doc, locator, text))
            return text
        except:
            logging.exception('获取元素:{}文本内容失败'.format(locator))
            self.save_screenshot(doc)
            raise

    # 7. 获取元素属性
    def get_element_attribute(self, locator, attr, doc=""):
        ele = self.find_element(locator, doc)
        logging.info('{0}获取元素:{1}的属性:{2}'.format(doc, locator, attr))
        try:
            ele_attr = ele.get_attribute(attr)
            logging.info('{0}元素:{1}的属性:{2}值为:{3}'.format(doc, locator, attr, ele_attr))
            return ele_attr
        except:
            logging.exception('{}获取元素:{}的属性失败'.format(doc, locator))
            self.save_screenshot(doc)
            raise

    # 8. alert处理
    def switch_to_alert(self, timeout=30, poll_frequency=0.5, action='accept', doc=""):
        logging.info('{0}_切换alert弹框'.format(doc))
        try:
            WebDriverWait(self.driver, timeout, poll_frequency).until(EC.alert_is_present())
            alert = self.driver.switch_to.alert
            value = alert.text
            logging.info('{0}当前弹框内容为:{1}'.format(doc, value))
            if action == 'accept':
                alert.accept()
            elif action == 'dismiss':
                alert.dismiss()
            return value
        except:
            logging.exception('{}弹框操作失败!'.format(doc))
            self.save_screenshot(doc)
            raise

    # 9. 保存截图
    def save_screenshot(self, doc):
        # 图片名称:模块名_页面名称_操作名称_年-月-日_时分秒.png
        # filePath = "截图路径" + "{0}".format(time.strftime("%Y%m%d%H%M%S"))
        filePath = screenshots_path + "{0}_{1}.png".format(doc, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
        try:
            self.driver.save_screenshot(filePath)
            logging.info("截取网页成功,文件路径为:{}".format(filePath))
        except:
            logging.exception('保存网页失败!')
            raise

    # 10. 滚动条处理
    def scrollbal_handle(self,url,mode='foot',doc=""):
        global js
        logging.info('{}进行滚动条操作'.format(doc))
        try:
            self.driver.get(url)
            if mode=='top':
                # 滚动到顶部
                js = "window.scrollTo(0,0)"
                self.driver.execute_script(js)
            else:
                # 滚动到底部
                js = "window.scrollTo(0,document.body.scrollHeight)"
                self.driver.execute_script(js)
            logging.info('{}滚动成功'.format(doc))
        except:
            logging.exception('{}滚动操作失败'.format(doc))
            self.save_screenshot(doc)
            raise

    # 11. 上传操作
    def upload_file(self, UpfilePath,doc=""):
        logging.info('{}进行文件上传'.format(doc))
        try:
            dialog = win32gui.FindWindow('#32770', '打开')  # 一级
            # 二级窗口
            ComBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComBoxEx32', None)
            # 三级窗口
            ComboBox = win32gui.FindWindowEx(ComBoxEx32, 0, 'ComboBox', None)
            # 四级窗口
            edit = win32gui.FindWindowEx(ComboBox, 0, 'Edit', None)
            button = win32gui.FindWindowEx(dialog, 0, 'Button', "打开(&0)")

            # 操作
            # 输入文件地址
            win32gui.SendMessage(edit, win32con.WM_SETTEXT, None, UpfilePath)  # 发送文件路径
            # 打开文件按钮
            win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)  # 点击打开按钮
            logging.info('{}文件上传成功'.format(doc))
        except:
            logging.exception('{}文件上传操作失败'.format(doc))
            self.save_screenshot(doc)
            raise

    # 12. iframe切换
    def switch_to_frame(self,locator,doc=""):
        ele = self.find_element(locator)
        logging.info('{}表单切换'.format(doc))
        try:
            self.driver.switch_to.frame(ele)
            logging.info('{}切换表单成功'.format(doc))
        except:
            logging.exception('{}切换表单失败!'.format(doc))
            self.save_screenshot(doc)
            raise

    # 13. 窗口切换
    def switch_to_window(self, window_reference, timeout=30, poll_frequency=0.5, window_handles=None, doc=""):
        logging.info("{0}_切换窗口".format(doc))
        try:
            if window_reference == "new":
                if window_handles:
                    WebDriverWait(timeout, poll_frequency).until(EC.new_window_is_opened(window_handles))
                    current_window_handles = self.driver.window_handles
                    self.driver.switch_to.window(current_window_handles[-1])
                else:
                    logging.exception("打开新窗口时,请传入window_handles参数")
                    raise ("打开新窗口时,请传入window_handles参数")
            elif window_reference == "default":
                self.driver.switch_to.default_content()
            else:
                self.driver.switch_to.window(window_reference)
            logging.info("{0}_切换窗口成功".format(doc))
        except:
            logging.exception("{0}_切换窗口失败".format(doc))
            self.save_screenshot(doc)
            raise

    # 14. 执行js
    def execute_script(self, js_str, element_info=None,doc=""):
        logging.info('{}执行js'.format(doc))
        try:
            if element_info:
                self.driver.execute_script(js_str)
            else:
                self.driver.execute_script(js_str, None)
            logging.info('{}执行js成功'.format(doc))
        except:
            logging.exception('{}执行js操作失败'.format(doc))
            self.save_screenshot(doc)
            raise

    # 15. 鼠标事件
    # 元素鼠标操作:右击-测试OK
    def context_click(self, locator):
        mouse = ActionChains(self.driver)
        ele = self.find_element(self,locator)
        logging.info('{}元素进行右击操作'.format(locator))
        mouse.context_click(ele).perform()
    # 元素鼠标操作:移动到该元素上--测试OK
    def move_to_element_by_mouse(self, locator):
        ele = self.find_element(locator)
        mouse = ActionChains(self.driver)
        logging.info('将鼠标移动到{}元素上'.format(locator))
        mouse.move_to_element(ele).perform()
    # 长按元素
    def long_press_element(self, locator, seconds):
        ele = self.find_element(locator)
        logging.info('将鼠标长按到{}元素上后松开'.format(locator))
        mouse = ActionChains(self.driver)
        mouse.click_and_hold(ele).pause(seconds).release(ele)

    def scrollIntoView(self, locator):
        ele = self.find_element(locator)
        logging.info('将滚动条滚动至{}元素可见'.format(locator))
        self.driver.execute_script('arguments[0].scrollIntoView();', ele)
        time.sleep(1)

    # 16. 键盘事件
    # 删除内容-测试OK
    def back_space(self, locator):
        ele = self.find_element(locator)
        logging.info('{0}元素操作back_space'.format(locator))
        ele.send_keys(Keys.BACK_SPACE)
    # 清空内容--测试OK
    def clear_input(self,locator):
        ele = self.find_element(locator)
        logging.info('{}元素输入框操作清空'.format(locator))
        ele.clear()
    # 按回车--测试OK
    def enter(self, locator):
        ele = self.find_element(locator)
        logging.info('{}元素进行回车键操作'.format(logging))
        ele.send_keys(Keys.ENTER)
    # 全选  Ctrl+a--测试OK
    def ctrl_a(self,locator):
        ele = self.find_element(locator)
        logging.info('{}元素输入框内容进行全选操作'.format(locator))
        ele.send_keys(Keys.CONTROL, 'a')
    # 粘贴 Ctrl +x--测试OK
    def ctrl_x(self,locator):
        ele = self.find_element(locator)
        logging.info('{}元素输入框内容进行剪切操作'.format(locator))
        ele.send_keys(Keys.CONTROL, 'x')
    # 粘贴 Ctrl +v--测试OK
    def ctrl_v(self, locator):
        ele = self.find_element(locator)
        logging.info('{}元素输入框内容进行粘贴操作'.format(locator))
        ele.send_keys(Keys.CONTROL, 'v')


    # 17. 等待操作
    def implicitly_wait(self, seconds=30):
        self.driver.implicitly_wait(seconds)
    def wait(self, seconds=20):
        time.sleep(seconds)

    # 18.浏览器操作
    def open_url(self, url):
        self.driver.get(url)
        logging.info('打开URL地址%s;' % url)
    def set_browser_max(self):
        self.driver.maximize_window()
        logging.info("设置浏览器的最大化")
    def close_tab(self):
        self.driver.close()
        logging.info('关闭当前的tab页签')
    def set_browser_min(self):
        self.driver.minimize_window()
        logging.info("设置浏览器的最小化")
    def browser_refresh(self):
        self.driver.refresh()
        logging.info("浏览器的刷新操作")
    def get_title(self):
        value = self.driver.title
        logging.info("获取网页的标题为:%s" % value)
        return value
    def quit_browser(self):
        self.driver.quit()
        logging.info("关闭浏览器")

2.2 file_path.py 路径文件

# —— coding :utf-8 ——
# @time:    2020/10/7 20:58
# @IDE:     webTest_frmewok_v2.0
# @Author:  jsonLiu
# @Email:   xxxxxxx@qq.com
# @File:    file_path.py
import os

# base_path = os.path.split(os.path.split(os.path.realpath(__file__))[0])[0] 二选1
base_path = os.path.split(os.path.split(os.path.abspath(__file__))[0])[0]

# 测试数据路径
TestDatas_path = os.path.join(base_path, 'TestDatas')

# 测试用例路径
TestCases_path = os.path.join(base_path, 'TestCases')

# 报告路径
reports_path = os.path.join(base_path, r'Outputs\reports')
allure_reports_path = os.path.join(base_path,r'Outputs\allure_reports')

# 截图路径
screenshots_path = os.path.join(base_path, r'Outputs\screenshots')

# 日志路径
logs_path = os.path.join(base_path, r'Outputs\logs')

# config_dir = os.path.join(base_path,'Config')

if __name__ == '__main__':
    print(logs_path)

2.3 my_log.py 自定义日志配置文件

import logging
from logging.handlers import RotatingFileHandler
import time
from Common import file_dir

fmt = " %(asctime)s  %(levelname)s %(filename)s %(funcName)s [ line:%(lineno)d ] %(message)s"
datefmt = '%a, %d %b %Y %H:%M:%S'

handler_1 = logging.StreamHandler()

curTime = time.strftime("%Y-%m-%d %H%M", time.localtime())

handler_2 = RotatingFileHandler(file_dir.logs_path + "/Web_Autotest_{0}.log".format(curTime), backupCount=20, encoding='utf-8')

#设置rootlogger 的输出内容形式,输出渠道
logging.basicConfig(format=fmt,datefmt=datefmt,level=logging.INFO,handlers=[handler_1,handler_2])

2.4 send_email.py 发送邮件文件

# —— coding :utf-8 ——
# @time:    2020/10/7 20:59
# @IDE:     webTest_frmewok_v2.0
# @Author:  jsonLiu
# @Email:   xxxxxxx@qq.com
# @File:    send_email.py
"""
使用一个邮箱向另一个邮箱发送测试报告的html文件,这里需要对发送邮件的邮箱进行设置,获取邮箱授权码。
username=“发送邮件的邮箱”, password=“邮箱授权码”
这里要特别注意password不是邮箱密码而是邮箱授权码。
mail_server = "发送邮箱的服务器地址"
这里常用的有 qq邮箱——"stmp.qq.com", 163邮箱——"stmp.163.com"
其他邮箱服务器地址可自行百度
"""
import os
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import time

# 自动发送邮件
class SendEmail():
    def send_email(self, new_report):
        # 读取测试报告中的内容作为邮件的内容
        with open(new_report, 'r', encoding='utf8') as f:
            mail_body = f.read()
        # 发件人地址
        send_addr = 'xxxxxx@qq.com'
        # 收件人地址
        reciver_addr = 'xxxxx@163.com'
        # 发送邮箱的服务器地址 qq邮箱是'smtp.qq.com', 163邮箱是'smtp.163.com'
        mail_server = 'smtp.qq.com'
        now = time.strftime("%Y-%m-%d %H:%M:%S")
        # 邮件标题
        subject = '接口自动化测试报告' + now
        # 发件人的邮箱及邮箱授权码
        username = 'xxxxx@qq.com'
        password = 'moasmyxgojcgbbch'  # 注意这里是邮箱的授权码而不是邮箱密码
        # 邮箱的内容和标题
        message = MIMEText(mail_body, 'html', 'utf8')   # MIMEText(邮箱主体内容,内容类型,字符集)
        message['Subject'] = Header(subject, charset='utf8')
        # 发送邮件,使用的使smtp协议
        smtp = smtplib.SMTP()
        smtp.connect(mail_server)
        smtp.login(username, password)
        smtp.sendmail(send_addr, reciver_addr.split(','), message.as_string())
        smtp.quit()

    # 获取最新的测试报告地址
    def acquire_report_address(self, reports_address):
        # 测试报告文件夹中的所有文件加入到列表
        test_reports_list = os.listdir(reports_address)
        # 按照升序排序生成新的列表
        new_test_reports_list = sorted(test_reports_list)
        # 获取最新的测试报告
        the_last_report = new_test_reports_list[-1]
        # 最新的测试报告地址
        the_last_report_address = os.path.join(reports_address, the_last_report)
        return the_last_report_address




if __name__ == '__main__':
    # 测试报告存放位置
    test_reports_address = '../test_result/html_report'
    # 查找最新生成的测试报告地址
    new_report_addr = SendEmail().acquire_report_address(test_reports_address)
    # 自动发送邮件
    SendEmail().send_email(new_report_addr)
3. 输出层

此前已经解析,不再重复

4. 页面元素定位层

4.1 indexpage_locators.py 首页元素定位文件

from selenium.webdriver.common.by import By
# 用户名
user_link = (By.XPATH,'//a[@href="/Member/index.html"]')
# 投标按钮
bid_button = (By.XPATH,'//*[text()="抢投标"]')    #//a[@class="btn btn-special"]

4.2 investpage_locators.py 投资页面元素定位文件

# —— coding :utf-8 ——
# @time:    2020/10/7 20:59
# @IDE:     webTest_frmewok_v2.0
# @Author:  jsonLiu
# @Email:   xxxxxxx@qq.com
# @File:    investpage_locators.py
from selenium.webdriver.common.by import By
# 投资输入框
money_input = (By.XPATH,'//input[contains(@class,"invest-unit-investinput")]')

#投标点击按钮
invest_button = (By.XPATH,'//div[@class="body"]//button')

# 投资成功弹窗的查看并激活按钮
active_button_on_success_pop = (By.XPATH,'//div[@class="layui-layer-content"]//button')

# 投标按钮上的错误信息
errorMsg_from_investButton = (By.XPATH,'//div[@class="layui-layer-content"]')

# 页面中间的错误提示信息
errorMsg_from_pageCenter = (By.XPATH,'//div/button[@class="btn btn-special height_style"]/text()')

4.3 loginpage_locators.py 登录页元素定位文件

4.4 其他页面元素定位根据需求自行创建封装

5. 页面对象层(操作方法)

5.1 index_page.py

# —— coding :utf-8 ——
# @time:    2020/10/7 21:00
# @IDE:     webTest_frmewok_v2.0
# @Author:  jsonLiu
# @Email:  xxxxxxx@qq.com
# @File:    index_page.py

import random
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from PageLocators import indexpage_locators as loc
class IndexPage:
    def __init__(self,driver):
        self.driver = driver
    def isExist_logout_ele(self):
        # 等待5s,元素没有出现 //a[@href="/Index/logout.html"]
        # 如果存在返回True,如果不存在,返回False
        try:
            WebDriverWait(self.driver, 5).until(EC.visibility_of_element_located((By.XPATH, '//a[@href="/Index/logout.html"]')))
            return True
        except:
            return False

    # 选标操作 --默认选第一个 = 元素定位的时候,过滤掉不可以投的标
    def click_first_bid(self):
        WebDriverWait(self.driver,10).until(EC.visibility_of_element_located(loc.bid_button))
        self.driver.find_element(*loc.bid_button).click()
    # 随机选一个标 //*[text()="抢投标"]
    def click_bid_by_random(self):
        # 找到所有符合的标
        WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(loc.bid_button))
        eles = self.driver.find_elements(*loc.bid_button)
        # 随机数
        index = random.randint(0,len(eles)-1)
        eles[index].click()

5.2 login_page.py

# —— coding :utf-8 ——
# @time:    2020/10/7 21:01
# @IDE:     webTest_frmewok_v2.0
# @Author:  jsonLiu
# @Email:  xxxxxxx@qq.com
# @File:    login_page.py
from PageLocators.loginpage_locators import LoginPageLocator as loc
from Common.base_page import BasePage

class LoginPage(BasePage):
    '''登录页面类'''
    # 登录操作
    def login(self, username, password, remember_user=True):
        # 输入用户名
        # 输入密码
        # 点击登录
        doc = "登录页面_登录功能"
        self.wait_eleVisible(loc.user_input,doc=doc)
        self.input_text(loc.user_input,username,doc)
        self.input_text(loc.pwd_input,password,doc)
        # 判断remember_user的值,决定是否勾选
        self.click_element(loc.login_but,doc)

    # 获取错误提示信息 ----登录区域
    def get_errorMsg_from_loginArea(self):
        doc = "登录页面_获取登录区域错误提示信息"
        self.wait_eleVisible(loc.get_errorMsg_from_login,doc=doc)
        return self.get_element_text(loc.get_errorMsg_from_login,doc)

    # 获取错误提示信息---中间区域
    def get_login_wrongPwd_noRegArea(self):
        doc = "登录页面_获取中间区域错误提示信息"
        self.wait_eleVisible(loc.get_login_wrongPwd_noReg,poll_frequency=0.2,doc=doc) # 错误的密码和没有注册提示信息在中间区域显示
        return self.get_element_text(loc.get_login_wrongPwd_noReg,doc)

5.3 其他页面元素对象操作方法根据需求自行创建函数封装

6. 测试用例层

6.1 conftest.py前后置操作文件,如打开浏览器、关闭浏览器、浏览器最大化、刷新页面等

# —— coding :utf-8 ——
# @time:    2020/10/7 21:01
# @IDE:     webTest_frmewok_v2.0
# @Author:  jsonLiu
# @Email:  xxxxxxx@qq.com
# @File:    conftest.py
from selenium import webdriver
from TestDatas import Common_datas as CD
from PageObjects.login_page import LoginPage
import pytest


driver = None
# 声明是一个fixture
@pytest.fixture(scope="class")
def access_web():
    global driver
    # 前置操作
    print("所有用例执行之前,setup整个测试类执行一次")
    driver = webdriver.Chrome()
    driver.get(CD.web_login_url)
    lg = LoginPage(driver)
    yield (driver, lg)  # 分割线:返回值
    # 后置操作
    print("所有用例执行完成,tearDown整个测试类执行一次")
    driver.quit()

@pytest.fixture
def refresh_page():
    global driver
    driver = webdriver.Chrome()
    # 前置操作
    yield
    # 后置操作
    driver.refresh()

6.2 test_login.py

# —— coding :utf-8 ——
# @time:    2020/10/7 21:02
# @IDE:     webTest_frmewok_v2.0
# @Author:  jsonLiu
# @Email:   xxxxxx@qq.com
# @File:    test_login.py
import unittest
from selenium import webdriver
from PageObjects.login_page import LoginPage
from PageObjects.index_page import IndexPage
import ddt
from TestDatas import Common_datas as CD
from TestDatas import login_datas as LD
import pytest


@pytest.mark.usefixtures("access_web")
@pytest.mark.usefixtures("refresh_page")
class TestLogin():
    # TestCase中不能写__init__
    # @classmethod
    # def setUpClass(cls):
    #     #通过excel读取本功能当中需要的所有测试数
    #     cls.driver = webdriver.Chrome()
    #     cls.driver.maximize_window()
    #     cls.driver.get(CD.web_login_url)
    #     cls.lg = LoginPage(cls.driver)
    #
    # @classmethod
    # def tearDownClass(cls):
    #     cls.driver.quit()
    # # def setUp(self):
    # #     pass
    # def tearDown(self):
    #     '''后置'''
    #     # 正常用例 -登录成功
    #     self.driver.refresh()

    # 异常用例 - 错误的手机号格式(大于11位、小于11位、为空、不在号码段) ddt
    @pytest.mark.parametrize("data", LD.phone_data)  # 参数化,把LD.phone_data的测试数据交给自定义参数名为data的参数
    def test_login_0_user_wrongFormat(self, data, access_web):
        # 步骤 输入用户名:xxx,密码:xxx,点击登录
        access_web[1].login(data["user"], data["password"])
        # 断言 登录页面 提示:请输入正确手机号
        # 对别文件内容与期望值是否相等
        assert (access_web[0].get_errorMsg_from_loginArea(), data["check"])

    # 手机号没有注册
    @pytest.mark.parametrize("caseData", LD.wrongPwd_noReg_data)
    def test_login_1_wrongPwd_noReg(self, caseData,access_web ):
        # 步骤:输入用户名:xxx, 密码:xxx 点击登录
        access_web["user"].login(caseData["user"],caseData["password"])
        # 断言: 登录页面 页面中间提示:此账号没有经过授权,请联系管理员! / 密码错误
        # 登录页面中, --获取提示框文本内容
        # 对比文本内容与期望值是否相等
        assert (access_web[0].get_errorMsg_from_loginArea(), caseData["check"])

    # fixture的函数名称用来接收它的返回值
    @pytest.mark.smoke
    def test_login_2_normal(self, access_web):
        # 步骤 输入用户名:xxx,密码:xxx,点击登录
        access_web[1].login(LD.success_data["user"], LD.success_data["password"])
        # 断言 首页当中能找到“我的帐户”或“退出"关键字
        assert IndexPage(access_web[0]).isExist_logout_ele()

if __name__ == '__main__':
    pass
7. 测试数据层

7.1 Common_datas.py

# 全局 --系统访问地址 --登录链接
web_login_url = "http://path_url/Index/login.html"

web_invest_url = "http://path_url/loan/loan_detail/Id/25750.html"

7.2 login_datas.py

# 正常用例 -登录成功
success_data = {"user":"13457681358","password":"123456"}

# 异常用例 - 错误的手机号格式(大于11位、小于11位、为空、不在号码段)
phone_data = [
    {"user":"1345768135","password":"123456","check":"请输入正确的手机号"},  # 小于11位
    {"user":"134576813588","password":"123456","check":"请输入正确的手机号"}, #大于11位
    {"user":"","password":"123456","check":"请输入手机号"},  # 手机号为空
    {"user":"13457681358","password":"123456","check":"请输入正确的手机号"} # 不在手机号段
]

wrongPwd_noReg_data = [
    {"user":"13457681358","password":"12345","check":"帐号或密码错误!"},  # 密码错误
    {"user":"13457681357","password":"123456","check":"此账号没有经过授权,请联系管理员!"}, # 账号没有授权
]

7.3 其他测试数据文件根据项目需要自行创建

8. readme.md 帮助文件
web自动化测试基本框架
-Common
-Outputs
-PageLocators
-PageObjects
-TestCases
-TestDatas
-run.py

常用命令:
创建虚拟环境		mkvirtualenv -p python3 虚拟环境名字
查看虚拟环境		workon
切换虚拟环境   	workon 虚拟环境名字`
退出当前虚拟环境	deactivate
删除虚拟环境		rmvirtualenv 虚拟环境名字`
导入requirements.txt工具包命令: pip install -r requirements.txt
导入requirements.txt工具包命令: pip freeze > requirements.txt
安装命令: pip install 包名
移除命令: pip uninstall 包名
查看已安装: pip list
9. requirements.txt 项目依赖工具包
atomicwrites==1.4.0
attrs==20.2.0
colorama==0.4.3
ddt==1.4.1
iniconfig==1.0.1
more-itertools==8.5.0
packaging==20.4
pluggy==0.13.1
py==1.9.0
pyparsing==2.4.7
pytest==6.0.2
pytest-html==2.1.1
pytest-metadata==1.10.0
pytest-rerunfailures==9.1
pywin32==228
selenium==3.141.0
six==1.15.0
toml==0.10.1
urllib3==1.25.10
10.run.py 项目运行文件
import HTMLTestRunner
from  Common.file_path import *
import unittest
# 实例化套件对象
s = unittest.TestSuite()
# 1.实例化TestLoader对象
# 2. 使用discover找到一个目录下所有测试用例
# 使用s
loader = unittest.TestLoader()
s.addTests(loader.discover(testcases_dir))
# # 运行
# runner = unittest.TextTestRunner()
# runner.run()

fp = open(htmlreport_dir+'/autoTest_report.html','wb')
runner = HTMLTestRunner.HTMLTestRunner(
        stream=fp,
        title="单元测试报告",
        description="单元测试报告"

)
runner.run(s)

四、与Jenkins集成

关于allure报告与Jenkins集成

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐