博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
selenium 中装饰器作用
阅读量:6969 次
发布时间:2019-06-27

本文共 4456 字,大约阅读时间需要 14 分钟。

前面讲到unittest里面setUp可以在每次执行用例前执行,这样有效的减少了代码量,但是有个弊端,比如打开浏览器操作,每次执行用例时候都会重新打开,这样就会浪费很多时间。于是就想是不是可以只打开一次浏览器,执行完用例再关闭呢?这就需要用到装饰器(@classmethod)来解决了。

 

一、装饰器

1.用setUp与setUpClass区别

setup():每个测试case运行前运行

teardown():每个测试case运行完后执行
setUpClass():必须使用@classmethod 装饰器,所有case运行前只运行一次
tearDownClass():必须使用@classmethod装饰器,所有case运行完后只运行一次

2.@是修饰符,classmethod是python里的类方法

 

二、执行顺序

1.用类方法写几个简单case,可以对比这篇:

# coding:utf-8

import unittest
import time
class Test(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print "start!"
   

    @classmethod

    def tearDownClass(cls):
        time.sleep(1)
        print "end!"
    def test01(self):
        print "执行测试用例01"
    def test03(self):
        print "执行测试用例03"
    def test02(self):
        print "执行测试用例02"
    def addtest(self):
        print "add方法"
if __name__ == "__main__":
    unittest.main()

2.从执行结果可以看出,前置和后置在执行用例前只执行了一次。

start!

执行测试用例01
执行测试用例02
执行测试用例03
...end!
----------------------------------------------------------------------
Ran 3 tests in 1.001s

 

三、selenium实例

1.可以把打开浏览器操作放到前置setUpClass(cls)里,这样就可以实现打开一次浏览器,执行多个case了

# coding:utf-8

from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
import unittest
class BolgHome(unittest.TestCase):
    u'''博客首页'''
    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Firefox()
        url = "http://www.cnblogs.com/yoyoketang/"
        cls.driver.get(url)
        cls.driver.implicitly_wait(30)
    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()
    def test_01(self):
        u'''验证元素存在:博客园'''
        locator = ("id", "blog_nav_sitehome")
        text = u"博客园"
        result = EC.text_to_be_present_in_element(locator, text)(self.driver)
        self.assertTrue(result)
    def test_02(self):
        u'''验证元素存在:首页'''
        locator = ("id", "blog_nav_myhome")
        text = u"首页"
        result = EC.text_to_be_present_in_element(locator, text)(self.driver)
        self.assertTrue(result)
if __name__ == "__main__":
    unittest.main()

 

#!/usr/bin/env python

# coding=utf-8
__author__ = 'Luzhuo'
__date__ = '2017/5/4'
# decorator.py 装饰器
# 装饰器: 本质是函数, 用于装饰其他函数, 附加一些本身所没有的功能

# 函数就是变量
def num():
print("num")

num()

num = 1 # 函数就是变量
# num() # num的引用被指向1,不能再调用

# ========================================

# 高阶函数
def func_1():
print("func_1")

def func_2(func): # 接收函数变量
func()

func_2(func_1) # => func_1

# ========================================

# 闭包
def func_3(line):
# 闭包: 用于代码封装 和 复用
def comp(value): # 嵌套函数: 函数里再嵌套一个函数
# 函数set_line执行完(生命周期结束), 自由变量(line)仍存活于包裹内
if value >= line:
print("{} >= {}".format(value, line))
else:
print("{} < {}".format(value, line))

return comp

f = func_3(60) # 调用函数A(set_line()),返回函数B(cmp()),这个函数B就叫闭包

f(89) # => 89 >= 60
f(59) # => 59 < 60

# ========================================

# 装饰器, 在不修改my_average()代码的情况下,为其添加了一些功能(wrapper())
def dec_1(func):
def wrapper(num1, num2):

# --- 附加功能 ---

if num2 == 0:
print("num2 值不能为0")

return func(num1, num2)

return wrapper

# 普通调用方式
def average_1(num1, num2):
return num1 / num2

average_1 = dec_1(average_1)

print(average_1(5, 3)) # => 1.6666666666666667

# 使用@语法糖的方式
@dec_1 # (sum = dec(sum))
def sum_1(num1, num2):
return num1 + num2

print(sum_1(5, 3)) # => 8

# ========================================

# 能接收任何参数的通用装饰器
def dec_2(func):
def wrapper(*arg, **kwargs):

# --- 附加功能 ---

print("loging i ...")

return func(*arg, **kwargs)

return wrapper

@dec_2
def average_2(num1, num2):
return num1 / num2

print(average_2(5, 3)) # => loging i ... => 1.6666666666666667

@dec_2
def sum_2(*args):
return sum(args)

print(sum_2(5, 3, 2, 1)) # => loging i ... => 11

# ========================================

# 能接收不同参数的装饰器
def auth(auth_type): # 在外面套一层
def dec_3(func):
def wrapper(*arg, **kwargs):
# --- 附加功能 ---
if auth_type == "admin":
print("你是管理员")
elif auth_type == "user":
print("你是普通用户")
else:
print("你是外星人吗?")

return func(*arg, **kwargs)

return wrapper
return dec_3

# 普通调用方式
@auth(auth_type="admin")
def average_3(*arg):
return sum(arg) / len(arg)

print(average_3(1, 2, 3, 4, 5)) # => 你是管理员 => 3.0

@auth(auth_type="user")
def sum_3(*arg):
return sum(arg)

print(sum_3(5, 3, 2, 1)) # => 你是普通用户 => 11

# ========================================

# 使用多个装饰器
@dec_1
@dec_2
@auth(auth_type="admin")
def average_2(num1, num2):
return num1 / num2

# 执行顺序dec_1 => dec_2 => auth => average_2

print(average_2(5, 3)) # => loging i ... => 你是管理员 => 1.6666666666666667
---------------------

首先,程序开始从guoguo()执行了,结果它发现该函数前面有个@,就知道该函数被装饰了,那就先去看看装饰了哪些功能吧。

然后,该函数就作为参数进入到decorate()中,返回另一个函数test。

最后,test()中就把需要添加给guoguo()的功能写在此处,如果需要guoguo()的结果,就在需要的地方调用即可。

这就是我理解的装饰器,概况来说,就是把需要装饰的函数当做装饰器函数的参数,然后返回一个新函数,在新函数中实现装饰功能。

转载于:https://www.cnblogs.com/klb561/p/10085586.html

你可能感兴趣的文章
HDU 1823 Luck and Love 二维线段树
查看>>
ecshop二次开发常用代码
查看>>
GCD编程 之 略微提高篇
查看>>
第十四章 数字签名算法--RSA
查看>>
hdu 5056Boring count
查看>>
8个超炫酷仿苹果应用的HTML5动画
查看>>
Deep Learning for Nature Language Processing --- 第四讲(下)
查看>>
第一次打开Photoshop时的基本设置
查看>>
讲座:计算机专业及其学习
查看>>
makefile--目录搜索(八)
查看>>
2016年新一年的开始
查看>>
CentOS 7 启动、重启、chkconfig等命令已经合并为systemctl
查看>>
POI 中的CellRangeAddress 参数
查看>>
Http Request
查看>>
zepto和jquery的区别,zepto的不同使用8条小结
查看>>
sublime text 2安装及使用
查看>>
开源搜索引擎评估:lucene sphinx elasticsearch
查看>>
[转载]调整虚拟内存
查看>>
程序设计第二次作业<2>
查看>>
c++异常捕获
查看>>