zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【使用pytest重构项目】使用pytest重构unittest项目:解决函数依赖

pytest项目依赖重构 解决 函数 unittest 使用
2023-09-11 14:17:00 时间

前言

一直想学习自动化测试,但是都没行动,业余时间学习零零碎碎并记录20210420。

 

6、使用pytest重构项目

  • pytest框架介绍
  • pytest标记
  • pytest参数处理
  • pytest Fixtrue
  • pytest allure生成测试报告
  • 使用pytest重构项目

 

使用pytest重构unittest项目

1、用户登录重构代码

from time import sleep

import pytest
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait


# class TestUserLogin(unittest.TestCase):
class TestUserLogin(object):

    @classmethod
    # def setUp(cls) -> None:
    # 改成setup
    def setup(cls):
        cls.driver = webdriver.Chrome()
        cls.driver.get('http://localhost:8080/jpress/user/login')
        cls.driver.maximize_window()
    # def __init__(self):
    #     self.driver = webdriver.Chrome()
    #     self.driver.get('http://localhost:8080/jpress/user/login')
    #     # self.driver.maximize_window()



    # 测试用户登录,用户名错误
    @pytest.mark.skip  # 跳过执行
    def test1_user_login_userError(self):
        # 用户名为空
        user = ''  #实际正确的是amdin
        pwd = 'admin'
        expected = '账号不能为空'

        # 输入用户名
        self.driver.find_element_by_name('user').send_keys(user)
        # 输入密码
        self.driver.find_element_by_name('pwd').send_keys(pwd)
        # 点击登录
        self.driver.find_element_by_xpath('/html/body/div/div/div/form/div[3]/div/button').click()  #千万别忘记click

        # 因为有弹窗所以需要切换到弹窗上,并等待弹窗
        WebDriverWait(self.driver, 5).until(EC.alert_is_present())

        alert = self.driver.switch_to.alert
        # python 的断言
        # 获取弹窗上的文字来比较
        assert alert.text == expected
        sleep(2)
        alert.accept()

        sleep(2)

    # 测试用户登录成功
    def test2_user_login_ok(self):
        # 用户名为空
        user = 'admin'
        pwd = 'admin'
        expected = '用户中心'

        # 输入用户名
        self.driver.find_element_by_name('user').clear()    # 为了把上面案例输入的值清空
        self.driver.find_element_by_name('user').send_keys(user)
        # 输入密码
        self.driver.find_element_by_name('pwd').clear()
        self.driver.find_element_by_name('pwd').send_keys(pwd)
        # 点击登录
        # self.driver.find_element_by_xpath('/html/body/div/div/div/form/div[3]/div/button').click()
        self.driver.find_element_by_css_selector('body > div > div > div > form > div.row > div > button').click()
        # 等待标题
        WebDriverWait(self.driver, 5).until(EC.title_is(expected))

        sleep(3)
        #验证 因为没有错误弹窗  所以用到了title断言判断
        assert self.driver.title == expected


if __name__ == '__main__':
    # unittest.main()
    pytest.main(['-sv', 'test_user_login.py'])

运行结果

2、管理员登录重构代码

import os
import unittest
from time import sleep, strftime, localtime

import pytest
from PIL import Image
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

from lib.ShowapiRequest import ShowapiRequest

class TestAdminLogin(object):

    @classmethod
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.get('http://localhost:8080/jpress/admin/login')
        print('尝试管理员登录')


    # @pytest.mark.skip()  # 跳过执行
    # 测试管理员用户登录,验证码错误
    # @pytest.mark.skip # 跳过执行
    def test1_admin_login_Error(self):
        # 用户名为空
        user = 'admin'  #实际正确的是amdin
        pwd = 'admin'
        captcha = '123456'
        expected = '验证码不正确,请重新输入'

        # 输入用户名
        self.driver.find_element_by_name('user').send_keys(user)
        # 输入密码
        self.driver.find_element_by_name('pwd').send_keys(pwd)
        # 输入验证码
        self.driver.find_element_by_name('captcha').send_keys(captcha)
        # 点击登录
        self.driver.find_element_by_xpath('//*[@id="form"]/div[4]/div/button').click()  #千万别忘记click

        # 因为有弹窗所以需要切换到弹窗上,并等待弹窗
        WebDriverWait(self.driver, 5).until(EC.alert_is_present())

        alert = self.driver.switch_to.alert
        # python 的断言
        # 获取弹窗上的文字来比较
        assert alert.text == expected
        sleep(2)
        alert.accept()

        sleep(2)


    # 测试用户登录成功
    def test2_admin_login_ok(self):

        # 用户名为空
        user = 'admin'
        pwd = 'admin'
        expected = 'Jpress后台'

        # 输入用户名
        self.driver.find_element_by_name('user').clear()    # 为了把上面案例输入的值清空
        self.driver.find_element_by_name('user').send_keys(user)
        # 输入密码
        self.driver.find_element_by_name('pwd').clear()
        self.driver.find_element_by_name('pwd').send_keys(pwd)
    # 自动识别验证码test_yzmPro
    # captcha = util.test_yzmPro()  # 不知道为啥直接调用参数还是什么问题,直接把原来写的调用AI库识别复杂验证码拷贝过来调试了
        path = '/Users/zhengxiaofang/PycharmProjects_py3/Selenium_project/'
        path = os.path.join(path, 'screenshots')
        if not os.path.exists(path):  # 如果找不到/Users/zhengxiaofang/PycharmProjects_py3/Selenium_project/screenshots就创建
            os.mkdir(path)
        # 设置要截图的文件名:自定义名称+系统时间命名+后缀.png
        picture_name1 = '验证码未切' + strftime('%Y_%m_%d_%H_%M_%S', localtime()) + '.png'
        path = os.path.join(path, picture_name1)  # 截图1的路径+名称
        self.driver.get_screenshot_as_file(path)  # 截图保存
        print(path)

        # 找到验证码坐标,利用pil模块中的抠图方法crop,把图片抠出来,保存为picture_name2
        # yzm_img = browser.find_element_by_xpath('//*[@id="captchaimg"]')
        yzm_img = self.driver.find_element_by_id("captchaImg")
        print(yzm_img.location)  # 打印左上角坐标{'x': 547, 'y': 447}

        left = yzm_img.location['x']
        top = yzm_img.location['y']
        width = yzm_img.size['width'] + left
        height = yzm_img.size['height'] + top

        dpr = self.driver.execute_script(
            'return window.devicePixelRatio')  # execute_script():执行js,使devicePixelRatio 能够返回当前显示设备的物理像素分辨率与 CSS 像素分辨率的比率
        print(dpr)

        # # 打开截图1
        im = Image.open(path)
        # 把图片抠出来,保存为picture_name2
        img = im.crop((left * dpr, top * dpr, width * dpr, height * dpr))
        picture_name2 = '验证码切图' + strftime('%Y_%m_%d_%H_%M_%S', localtime()) + '.png'
        print(picture_name2)
        img.save(picture_name2)  # 这种方式图片默认是保存到main.py当前路径下

        # 这里是复杂验证码获取

        r = ShowapiRequest("http://route.showapi.com/184-4", "602469", "cff386bf98294645ab8c1acf2fc2c385")  # 密钥和密码用自己的

        r.addFilePara("image", picture_name2)
        r.addBodyPara("typeId", "34")
        r.addBodyPara("convert_to_jpg", "0")
        r.addBodyPara("needMorePrecise", "0")
        res = r.post()
        print(res.text)  # 返回信息
        # 取showapi_res_body中的result
        body = res.json()['showapi_res_body']
        print(body)

        # 取出验证码
        print(body['Result'])
    # 完成验证码识别,取出后,进去输入

        # 输入验证码
        self.driver.find_element_by_name('captcha').clear()
        self.driver.find_element_by_name('captcha').send_keys(captcha)
        # 点击登录
        self.driver.find_element_by_xpath('//*[@id="form"]/div[4]/div/button').click()  #千万别忘记click
        # 等待标题
        WebDriverWait(self.driver, 5).until(EC.title_is(expected))

        sleep(3)
        #验证 因为没有错误弹窗  所以用到了title断言判断
        assert self.driver.title == expected
        sleep(2)

if __name__ == '__main__':
    pytest.main(['-sv', 'test_admin_login.py'])

命令行,运行结果

3、增加文章和删除文章重构代码

#增加文章和删除文章重构

#增加文章和删除文章,重点是iframe的切入和切出以及弹窗的定位
import unittest

import pytest
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from time import sleep

from testcases.pytest.test_admin_login import TestAdminLogin


class TestArticle(object):
    # 先初始化登录
    def setup_class(self):
        self.login = TestAdminLogin()

    # 测试文章分类成功  因为需要依赖登录
    @pytest.mark.dependency(depends=['admin_login'], scope="module")
    # 测试添加文章
    def test_add_ok(self):
        title = '我的文章'
        content = '我的文章内容'
        expected = '保存成功!'

        # 点击文章
        self.login.driver.find_element_by_xpath('//*[@id="sidebar-menu"]/li[4]/a/span[1]').click()
        sleep(1)
        # 点击写文章
        self.login.driver.find_element_by_xpath('//*[@id="sidebar-menu"]/li[4]/ul/li[2]/a').click()
        sleep(1)
        # 填写文章标题
        self.login.driver.find_element_by_id('article-title').send_keys(title)

        frame1 = self.login.driver.find_element_by_xpath('//*[@id="cke_1_contents"]/iframe')
        # 切入iframe!!!
        self.login.driver.switch_to.frame(frame1)

        sleep(1)

        self.login.driver.find_element_by_xpath('/html/body').send_keys(content)

        # 切出(为了定位发布按钮)!!!
        self.login.driver.switch_to.default_content()

        # 点击发布按钮
        self.login.driver.find_element_by_xpath('//*[@id="form"]/div/div[2]/div[1]/div/button[1]').click()

        # 这个是浮窗的定位
        loc = (By.CLASS_NAME, 'toast-message')
        # 当浮窗出现,取出文本进行比较,
        WebDriverWait(self.login.driver, 5).until(EC.visibility_of_element_located(loc))
        msg = self.login.driver.find_element(*loc).text

        assert msg == expected


    # 测试删除单个文章
    @pytest.mark.skip
    def test_delete_one_article_ok(self):
        # 点击文章
        self.login.driver.find_element_by_xpath('//*[@id="sidebar-menu"]/li[4]/a/span[1]').click()
        sleep(1)
        # 点击文章管理
        self.login.driver.find_element_by_xpath('//*[@id="sidebar-menu"]/li[4]/ul/li[1]/a]').click()
        sleep(1)

        # 找到第一个文章的链接。/html/body/div/div/section[3]/div/div/div/div[2]/table/tbody/tr[2]/td[2]/strong/a
        link = self.login.driver.find_element_by_xpath(
            '/html/body/div/div/section[3]/div/div/div/div[2]/table/tbody/tr[2]/td[2]/strong/a')
        # 鼠标移动到这个位置  鼠标键盘的操作
        ActionChains(self.login.driver).move_to_element(link).perform()

        sleep(1)

        # 如何判断删除文章成功:删除后的条数+1等于删除前的条数
        # 删除前文章数  统计复选框
        article_num = len(self.login.driver.find_elements_by_class_name('jp-actiontr'))

        # 删除,鼠标移动到垃圾箱,点击,即回收
        del_elem = self.login.driver.find_element_by_xpath(
            '/html/body/div/div/section[3]/div/div/div/div[2]/table/tbody/tr[2]/td[2]/div/div/a[3')
        del_elem.click()

        # 删除后文章数
        article_num2 = len(self.login.driver.find_elements_by_class_name('jp-actiontr'))

        # 断言删除后的条数+1等于删除前的条数
        assert article_num == article_num2 + 1


    # 测试删除所有文章
    @pytest.mark.skip
    def test_delete_all_article_ok(self):
        # 点击文章
        self.login.driver.find_element_by_xpath('//*[@id="sidebar-menu"]/li[4]/a/span[1]').click()
        sleep(1)
        # 点击文章管理
        self.login.driver.find_element_by_xpath('//*[@id="sidebar-menu"]/li[4]/ul/li[1]/a]').click()
        sleep(1)



        # 找到全选按钮。
        checkbox = self.login.driver.find_element_by_xpath(
            '/html/body/div/div/section[3]/div/div/div/div[2]/table/tbody/tr[1]/th[1]/input')
        # 点击全选按钮
        checkbox.click()

        # 点击所有文章,查看为0
        self.login.driver.find_element_by_id('batchDel').click()

        WebDriverWait(self.login.driver, 5).until(EC.alert_is_present())
        alert = self.login.driver.switch_to.alert
        alert.accept()

        sleep(1)

运行结果:

“永不放弃,总有希望在前面等待!”送给自己,也送给正在阅读文章的博友们~