selenium下如何解决用例依赖问题

发表于:2021-4-20 09:26

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:桃子    来源:51Testing软件测试网原创

  题记
  本文主要讲述不在框架下和在pytest框架下selenium如何解决用例之间的依赖问题。

  问题情境
  有这样一种现象,想要发布文章或者删除文章内容,必须通过登录后才可以对具体功能操作,那么我们就必须解决用例依赖问题。
  或者你可能会想到传url地址直接传入发布文章地址不可以么。我这样操作后,前端返回的页面还是登录页面,可见这样操作是不可以的。

  非框架下用例依赖
  下面我们来看看不在框架内怎么实现用例之间的依赖,有两个地方需要注意。

  初始化函数和main()函数
  main函数用例设计时,根据用例前后顺序设计:
  实例化登录类->调用登录成功函数-》实例化文章发布类(login作为参数传入)。
if __name__ == '__main__':
  #实例化登录类
    login = Test_admin_login()
    #调用登录成功函数
    login.login_success()
    #实例化文章发布类
    testArticle = TestArticle(login)
    #调用发布文章成功函数
    testArticle.test_add_ok()

  初始化函数:传入login而非driver
  初始化函数:
def __init__(self, login):    
self.login = login

  pytest框架下用例依赖
  主要借助于@pytest.mark.dependency函数实现。

  使用方法:
  1.首先在被依赖函数前标记@pytest.mark.dependency();
  2.然后再依赖函数前@pytest.mark.dependency(depends=["‘被依赖函数名称’"])。
import pytest
@pytest.mark.dependency()
def test_01(test):
    assert False
@pytest.mark.dependency(depends=["test_01"])
def test_02(test):
    print("执行测试2")

  下面我们看看登录及文章分类的用例:

  被依赖函数登录功能
  使用@pytest.mark.dependency(name='admin_login')标记依赖函数:test_admin.py。
import time
import pytest
from selenium import webdriver #将webdriver驱动导入selenium框架中
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from util.util import *
class Test_admin_login(object):
    def setup_class(self):
         self.driver=webdriver.Chrome()
         self.driver.get('http://localhost:8888/jpress/admin/login')
         self.driver.maximize_window()
    login_data=[('wx','123456','666','验证码不正确,请重新输入'),
                ('wx','123456','234','JPress后台')]
    @pytest.mark.dependency(name='admin_login')
    @pytest.mark.parametrize('username,pwd,captcha,expect',login_data)
    def test1(self,username,pwd,captcha,expect):
        #测试数据
        #正确用户名
        self.driver.find_element_by_name('user').clear()
        self.driver.find_element_by_name('user').send_keys(username)
        # 正确密码
        self.driver.find_element_by_name('pwd').clear()
        self.driver.find_element_by_name('pwd').send_keys(pwd)
        if captcha!='666':
            # 正确的验证码
            js = "document.getElementsByTagName('img')[0].setAttribute('id','captchaimg')"
            self.driver.execute_script(js)
            captcha = get_code(self.driver, id='captchaimg', uname='luoditao', pwd='xinsheng2', )
            self.driver.find_element_by_name('captcha').clear()
            self.driver.find_element_by_name('captcha').send_keys(captcha)
            # 登录按钮
            self.driver.find_element_by_class_name('btn-flat').click()
            WebDriverWait(self.driver, 5).until(EC.title_is(expect))
            assert expect == self.driver.title
            time.sleep(3)
        else:
            #错误的验证码
            self.driver.find_element_by_name('captcha').clear()
            self.driver.find_element_by_name('captcha').send_keys(captcha)
            #登录按钮
            self.driver.find_element_by_class_name('btn-flat').click()
            WebDriverWait(self.driver,20).until(EC.alert_is_present())
            alert=self.driver.switch_to.alert
            assert alert.text==expect
            alert.accept()
            time.sleep(2)
if __name__ == '__main__':
    pytest.main(['test_admin_login.py'])

  依赖函数
  1.首先导入登录的用例from ddt.testadminlogin import *;
  2.初始化函数self.login = Testadminlogin();
  3.标记调用依赖的函数名@pytest.mark.dependency(name='admin_login')注意,每个函数前面都加上标记,比如下面有3条case就写3个。
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
import pytest
from selenium import webdriver
from ddt.test_admin_login import *
login_data=[('我的文章', '我的文章内容','文章保存成功。')]
class TestArticle(object):
    def setup_class(self):
        self.login = Test_admin_login()
    # 测试添加文章
    @pytest.mark.dependency(name='admin_login')
    @pytest.mark.parametrize('title,content,expected',login_data)
    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[1]/a').click()
        sleep(1)
        #新建
        self.login.driver.find_element_by_xpath('/html/body/div/div/section[3]/div/div/div/div[1]/div/div/a').click()
        sleep(1)
        #定位文章区域
        #标题
        self.login.driver.find_element_by_id('article-title').send_keys(title)
        sleep(1)
        #进入iframe
        frame1=self.login.driver.find_element_by_xpath('//*[@id="cke_1_contents"]/iframe')
        self.login.driver.switch_to.frame(frame1)
        sleep(1)
        #文章内容
        self.login.driver.find_element_by_xpath('/html/body').send_keys(content)
        #退出frame
        self.login.driver.switch_to.default_content()
        #发布按钮
        self.login.driver.find_element_by_class_name('btn-primary').click()
        loc=(By.CLASS_NAME,"toast-message")
        WebDriverWait(self.login.driver,5).until(EC.visibility_of_element_located(loc))
        message=self.login.driver.find_element(*loc).text
        assert message==expected
    # 测试删除单篇文章
    @pytest.mark.dependency(name='admin_login')
    def test_delete_one_article_ok(self):
        # 文章管理
        self.login.driver.find_element_by_xpath('//*[@id="sidebar-menu"]/li[4]/ul/li[1]/a').click()
        sleep(1)
        #删除前文章数
        beforenumber=len(self.login.driver.find_elements_by_class_name('jp-actiontr'))
        #鼠标悬停文章内容
        a=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(a).perform()
        #删除
        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]').click()
        sleep(1)
        #删除后文章数
        afternumber=len(self.login.driver.find_elements_by_class_name('jp-actiontr'))
        #验证删除后文章数=删除前文章数-1
        assert beforenumber==afternumber+1
    # 测试删除所有文章
    @pytest.mark.dependency(name='admin_login')
    def test_delete_all_article_ok(self):
        #文章管理
        self.login.driver.find_element_by_xpath('//*[@id="sidebar-menu"]/li[4]/ul/li[1]/a').click()
        #点击全部复选框
        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').click()
        sleep(1)
        self.login.driver.find_element_by_id('batchDel').click()
        sleep(1)
        WebDriverWait(self.login.driver,5).until(EC.alert_is_present())
        alert = self.login.driver.switch_to.alert
        alert.accept()
        sleep(1)
        #文章数目=0
        afternumber = len(self.login.driver.find_elements_by_class_name('jp-actiontr'))
        sleep(1)
        assert afternumber==0
if __name__ == '__main__':
    pytest.main(['test_article.py'])

  相比较而言,还是在框架下实现用例之间的调用比较简单。
  记住,只需要用一个函数@pytest.mark.dependency(name='adminlogin')就可以搞定,里面的name=adminlogin 每次调用时都统一,否则系统匹配不删就会报错。



版权声明:本文出自《51测试天地》第六十一期。51Testing软件测试网及相关内容提供者拥有51testing.com内容的全部版权,未经明确的书面许可,任何人或单位不得对本网站内容复制、转载或进行镜像,否则将追究法律责任
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号