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

一、装饰器

1.用setUp与setUpClass区别

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

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

二、执行顺序

1.用类方法写几个简单case,可以对比这篇:Selenium2+python自动化52-unittest执行顺序

# 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()的结果,就在需要的地方调用即可。

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

selenium 中装饰器作用的更多相关文章

  1. 8.Python中装饰器是什么?

    Python中装饰器是什么? A Python decorator is a specific change that we make in Python syntax to alter functi ...

  2. 第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法

    第7.18节 案例详解:Python类中装饰器@staticmethod定义的静态方法 上节介绍了Python中类的静态方法,本节将结合案例详细说明相关内容. 一.    案例说明 本节定义了类Sta ...

  3. Flask-Login中装饰器@login_manager.user_loader的作用及原理

    Flask-Login通过装饰器@login_required来检查访问视图函数的用户是否已登录,没有登录时会跳转到login_manager.login_view = 'auth.login'所注册 ...

  4. python中装饰器的原理

    装饰器这玩意挺有用,当时感觉各种绕,现在终于绕明白了,俺滴个大爷,还是要慢慢思考才能买明白各种的真谛,没事就来绕一绕 def outer(func): def inner(): print(" ...

  5. python中装饰器修复技术

    python装饰器@wraps作用-修复被装饰后的函数名等属性的改变 Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变), 为了 ...

  6. Python中装饰器(转)

    本文由 伯乐在线 - 7even 翻译,艾凌风 校稿.未经许可,禁止转载!英文出处:Simeon Franklin.欢迎加入翻译组. 好吧,我标题党了.作为 Python 教师,我发现理解装饰器是学生 ...

  7. Python中装饰器的用法

    定义: 装饰器本身就是一个函数 为其他函数提供附加功能 不改变源代码 不改变原调用方式 装饰器=高阶函数+嵌套函数 知识点: 函数本身就是一个变量(意味着可以被复制给一个变量:test=test(1) ...

  8. python flask route中装饰器的使用

    问题:route中的装饰器为什么感觉和平时使用的不太一样,装饰器带参数和不太参数有什么区别?被修饰的函数带参数和不带参数有什么区别? 测试1:装饰器不带参数,被修饰的函数也不带参数. def log( ...

  9. python中装饰器使用

    装饰器是对已有的模块进行装饰(添加新功能)的函数. 现有一段代码: import time def func1(): time.sleep(3) print("in the func1&qu ...

随机推荐

  1. 日记整理---->2016-11-01

    这里我们整理一下项目的流程,一般来说做一个模块之前.会有需求文档.页面原型和接口文档. 一. js获取radio的值 页面的html代码: <ul class="list-group& ...

  2. AVL树与红黑树

    平衡树是平时经常使用数据结构. C++/JAVA中的set与map都是通过红黑树实现的. 通过了解平衡树的实现原理,可以更清楚的理解map和set的使用场景. 下面介绍AVL树和红黑树. 1. AVL ...

  3. c++ 引用底层实现

    红色是我添加的,其他地方是原作者的. 主要是看了上面的这篇“从底层汇编理解 c++ 引用实现机制“的文章之后,觉得不错.就转了过来,同时,对文中的程序都在自己的机器上验证了一下. 使用的G++版本:g ...

  4. JS-鼠标跟随块(一个小圆点跟着鼠标跑)

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. JS-利用ajax获取json数据,并传入页面生成动态tab

    封装好的:ajax.js function ajax(url, fnSucc,fnFaild){ //1[创建] if(window.XMLHttpRequest){ var oAjax = new ...

  6. JS-cookie封装

    智能社学习笔记 <script type="text/javascript"> /*****设置cookie*****/ function setCookie(name ...

  7. outline的兼容性及使用限制

    outline 和 border的区别: outline不占据文档空间,border占据文档空间. outline无法单独设置上下左右,只要设置outline,必须所有的边都设置:border可以设置 ...

  8. Sun公司的产品AnswerBook存在多种漏洞

    一.未授权管理脚本访问漏洞: 1.受影响版本: Sun-AnswerBook2     1.2-1.4.2 2.攻击测试手段 http://a.b.c.d:8888/ab2/@AdminViewErr ...

  9. all index range ref eq_ref const system 索引type说明

    背景知识 在使用sql的过程中经常需要建立索引,而每种索引是怎么处罚的又是怎么起到作用的,首先必须知道索引和索引的类型. 索引类型type 我们可以清楚的看到type那一栏有index ALL eq_ ...

  10. 关于移动端rem 布局的一些总结

    1.rem是什么? rem(font size of the root element)是指相对于根元素的字体大小的单位 2.为什么web app要使用rem? 实现强大的屏幕适配布局(淘宝,腾讯,网 ...