3.4 unittest之装饰器(@classmethod)

3.4 unittest之装饰器(@classmethod)

前言
前面讲到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()
复制代码

       上述代码运行的顺序就是从上至下,而不再是每次执行完成一个testcase之后,执行一次teardownClass再进行下一个testcase。

  这样一来,退出浏览器仅仅执行一次即可,这样有一个不好的地方就是,teardownClass这个函数不能再进行每个测试用例的终结操作,比如:修改个人信息后恢复到登录成功后的状态,对当前测试用例的异常处理等。

  后来,本人尝试在tearDownClass后增加如下代码:

def tearDown(self):
    self.driver.refresh()
    self.assertEqual( [], self.verificationErrors )

     然后,果然每次测试用完成都会刷新当前页面,这样一来,每一个testcase的用例都能被终结函数tearDown结束,最后再执行tearDownClass关闭测试浏览器。

     需要说明的是:

  @classmethod是python本身的装饰器,所以他不要使用隶属于unittest框架下断言assertEqual。

  unittest本身也带有装饰器unittest.skip(),专门用于跳过testcase的装饰器,其用法如下:     

复制代码
 @unittest.skip(reason), skip装饰器:直接跳过装饰下的testcase,reason用来说明原因,下同。

 @unittest.skipIf(condition,reason), skipIf装饰器:condition条件为True时,跳过装饰下的testcase,计入skip的testcase执行次数。

 @unittest.skipUnless(condition,reason),skipUnless装饰器:condition条件为False时,跳过装饰下的testcase,计入skip的testcase执行次数。

 @unittest.expectedFailure(), expectedFailure装饰器:执行装饰下的testcase,执行失败则跳过该testcase,计入expected下成败的testcase次数。
复制代码

  一般来讲,使用@unittest.skipIf 或者 @unittest.skipUnless,应该也能实现@classmethod装饰器的效果, 想来只是实现起来相对来说较为麻烦。

posted @ 2018-06-14 17:29  lunvo  阅读(1423)  评论(0编辑  收藏  举报