前面讲到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. windows7中的“mklink命令”

    从 Vista 以后,微软将用户文件和用户的软件配置( AppData ) 明确划分开,并且全部存放在使用者的用户目录下. Linux早已这样做了,并且在Linux中可将 home 挂载为独立分区,而 ...

  2. C++11新特性之二——std::bind std::function 高级用法

    /* * File: main.cpp * Author: Vicky.H * Email: eclipser@163.com */ #include <iostream> #includ ...

  3. iOS开发 - 检测网络状态(WIFI、2G/3G/4G)

    本文转载至 http://blog.csdn.net/wangzi11322/article/details/45580917 检测网络状态 在网络应用中,需要对用户设备的网络状态进行实时监控,目的是 ...

  4. 《C++ Primer Plus》第10章 对象和类 学习笔记

    面向对象编程强调的是程序如何表示数据.使用 OOP 方法解决编程问题的第一步是根据它与程序之间的接口来描述数据,从而指定如何使用数据.然后,设计一个类来实现该接口.一般来说,私有数据成员存储信息,公有 ...

  5. 原来 CSS 与 JS 是这样阻塞 DOM 解析和渲染的

    hello~各位亲爱的看官老爷们大家好.估计大家都听过,尽量将CSS放头部,JS放底部,这样可以提高页面的性能.然而,为什么呢?大家有考虑过么?很长一段时间,我都是知其然而不知其所以然,强行背下来应付 ...

  6. ceph 存储安装部署

    环境准备 1.三台服务器 cephnode01 192.168.254.83 cephnode02 192.168.254.84 cephnode03 192.168.254.85 2.基本环境配置 ...

  7. python实现HTTP代理的思路和Demo

    一.首先什么是代理: 代理其实就是中间转发的那个玩意,所以在代码逻辑上也是如此的. 二.Python写http代理的基本逻辑: (1)接受浏览器发出的请求,解析,拼凑成该有的样子,然后使用套接字发出去 ...

  8. 1.border-image

    1.设置在元素围绕的border的图片,用图片代替边框 语法: broder-image-source:图片 border-image-slice:切下的区域,数字|百分比(相对于图像的高度和宽度) ...

  9. NodeJS收发GET和POST请求

    目录: 一 express框架接收 二 接收Get 三 发送Get 四 接收Post 五 发送Post 一 express框架接收 app.get('/',function(req,res) { va ...

  10. 【BZOJ2599】[IOI2011]Race 树的点分治

    [BZOJ2599][IOI2011]Race Description 给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 100000 ...