appium python unittest_python unittest全面解析

import unittest

import os

class MyUnittest(unittest.TestCase):

def setUp(self) -> None:

print("setUp_每运行一次用例都会执行一次")

self.name = "hi"

print("setUp_name_%s" % self.name)

def tearDown(self) -> None:

print("tearDown_每结束一次用例都会执行一次")

print("tearDown_name_%s" % self.name)

@classmethod

def setUpClass(cls) -> None:

print("setUpClass_整个测试开始后执行,只执行一次")

cls.func = "setUpClass"

print("setUpClass_func_%s" % cls.func)

@classmethod

def tearDownClass(cls) -> None:

print("tearDownClass_整个测试完成后执行,只执行一次")

print("tearDownClass_func_%s" % cls.func)

def test_add(self):

print("测试函数:test_add")

self.name = "test_add"

print("setUpClass_cls.func_%s" % self.func)

def test_subtract(self):

print("测试函数:test_subtract")

self.name = "test_subtract"

self.func = "test_subtract"

if __name__ == "__main__":

# 运行方式一

unittest.main()

执行结果

setUpClass_整个测试开始后执行,只执行一次

setUpClass_func_setUpClass

test_add (ut_module.ut1_test.MyUnittest) ... setUp_每运行一次用例都会执行一次

setUp_name_hi

测试函数:test_add

setUpClass_cls.func_setUpClass

tearDown_每结束一次用例都会执行一次

tearDown_name_test_add

ok

test_subtract (ut_module.ut1_test.MyUnittest) ... setUp_每运行一次用例都会执行一次

setUp_name_hi

测试函数:test_subtract

tearDown_每结束一次用例都会执行一次

tearDown_name_test_subtract

ok

tearDownClass_整个测试完成后执行,只执行一次

tearDownClass_func_setUpClass

----------------------------------------------------------------------

Ran 2 tests in 0.003s

OK

测试分析

结果分析

setUp初始化的值可以改变

setUp_name_hi

测试函数:test_add

setUpClass_cls.func_setUpClass

tearDown_每结束一次用例都会执行一次

tearDown_name_test_add

setUp中的self.name的值,在测试函数中是可以被改变的,一开始name为hi,后面为test_add

setUpClass的的值无法改变

在def setUpClass赋值

self.func = "setUpClass"

在 def test_subtract中赋值

self.func = "test_subtract"

# 执行结果

setUpClass_整个测试开始后执行,只执行一次

setUpClass_func_setUpClass

.....

tearDownClass_整个测试完成后执行,只执行一次

tearDownClass_func_setUpClass

setUpClass初始化的值在函数中无法改变,应该是cls和self的指向不一样

setUp和setUpClass

每个用例都要独立,也就是每个用执行时,都会重开设备,就使用setup,比如appium中的driver

若想复用某个初始化条件,单不期望每个用例都重启再打开,可以使用setUpClass

在使用appium时,用setUp频繁初始化driver造成执行用例时间太长,可以使用setUpClass初始化driver,结合launch-app达到每个用例不重启,同时解决依赖关系的问题

不同的运行unittest的方式

方式一

unittest.main()

方式二

# 构造测试集

suite = unittest.TestSuite()

suite.addTest(MyUnittest("test_add"))

suite.addTest(MyUnittest("test_subtract"))

# 执行测试

runner = unittest.TextTestRunner()

runner.run(suite)

方式三

# TestLoader 用来加载TestCase到TestSuite中的,其中有几个 loadTestsFrom__()方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite实例

# TestSuite 测试套件集合,最终将传递给testRunner进行测试执行

# TextTestRunner 用来执行测试用例,将测试结果保存在TextTestResult中

# 此用法可以同时测试多个类

suite1 = unittest.TestLoader().loadTestsFromTestCase(MyUnittest)

suite2 = unittest.TestLoader().loadTestsFromTestCase(MyUnittest1)

suite = unittest.TestSuite([suite1, suite2 ])

unittest.TextTestRunner(verbosity=2).run(suite)

方式四

# 进入到测试目录

os.chdir(".//ut_module")

os.system("python -m unittest -v ut1_test")

方式五,直接到终端中输入命令

# 测试某个类下的所有函数

D:\project\ut>python -m unittest -v ut_module.ut1_test

# 测试类中某一个函数

D:\project\ut>python -m unittest -v ut_module.ut1_test.MyUnittest.test_add

# 执行模块下所有test结尾的文件

D:\project\ut>python -m unittest discover D:\project\ut\ut_module "*_test.py"

# 同时执行多个测试类下的测试函数

D:\project\ut>python -m unittest ut_module.ut1_test.MyUnittest.test_add ut_module.ut2_test.MyUnittest.test_subtract1

其他扩展

unittest的条件装饰器的使用

class MyTestCase(unittest.TestCase):

@unittest.skip("demonstrating skipping")

def test_nothing(self):

self.fail("shouldn't happen")

@unittest.skipIf(mylib.__version__ < (1, 3),

"not supported in this library version")

def test_format(self):

# Tests that work for only a certain version of the library.

pass

@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")

def test_windows_support(self):

# windows specific testing code

pass

def test_maybe_skipped(self):

if not external_resource_available():

self.skipTest("external resource not available")

# test code that depends on the external resource

pass

@unittest.expectedFailure

def test_fail(self):

self.assertEqual(1, 0, "broken")

@unittest.skip("showing class skipping")

class MySkippedTestCase(unittest.TestCase):

def test_not_run(self):

pass

@unittest.skip(reason)

跳过被此装饰器装饰的测试。 reason 为测试被跳过的原因。

@unittest.skipIf(condition, reason)

当 condition 为真时,跳过被装饰的测试。

@unittest.skipUnless(condition, reason)

跳过被装饰的测试,除非 condition 为真。

@unittest.expectedFailure

把测试标记为预计失败。如果测试不通过,会被认为测试成功;如果测试通过了,则被认为是测试失败。

exception unittest.SkipTest(reason)

引发此异常以跳过一个测试。

参数化

在使用unittest时,希望testcase传参给unittest,下面时用appium的一个伪代码

class ParametrizedTestCase(unittest.TestCase):

""" TestCase classes that want to be parametrized should

inherit from this class.

"""

def __init__(self, methodName='runTest', param=None):

super(ParametrizedTestCase, self).__init__(methodName)

# 得到testcase传来的参数

global devicess

devicess = param

@classmethod

def setUpClass(cls):

pass

cls.driver = get_driver(devicess)

cls.logTest = myLog().getLog(cls.devicesName) # 每个设备实例化一个日志记录器

def setUp(self):

pass

@classmethod

def tearDownClass(cls):

cls.driver.close_app()

cls.driver.quit()

pass

def tearDown(self):

pass

@staticmethod

def parametrize(testcase_klass, param=None):

testloader = unittest.TestLoader()

testnames = testloader.getTestCaseNames(testcase_klass)

suite = unittest.TestSuite()

for name in testnames:

suite.addTest(testcase_klass(name, param=param))

return suite

class HomeTest(ParametrizedTestCase):

def testFirstOpen(self):

app = {"logTest": self.logTest, "driver": self.driver, "path": PATH("../yamls/home/firstOpen.yaml"),

"device": self.devicesName, "caseName": sys._getframe().f_code.co_name}

page = FirstOpenPage(app)

page.operate()

page.checkPoint()

@classmethod

def setUpClass(cls):

super(HomeTest, cls).setUpClass()

@classmethod

def tearDownClass(cls):

super(HomeTest, cls).tearDownClass()

if __name__ == '__main__':

devices = {"设备信息"}

suite = unittest.TestSuite()

suite.addTest(ParametrizedTestCase.parametrize(HomeTest, param=devices))

unittest.TextTestRunner(verbosity=2).run(suite)

ddt

pip install ddt

使用json

新建文件 test_data_list.json:

[

"Hello",

"Goodbye"

]

新建文件 test_data_dict.json:

{

"unsorted_list": [ 10, 12, 15 ],

"sorted_list": [ 15, 12, 50 ]

}

实例代码

import unittest

from ddt import ddt, file_data

from ddt_demo.mycode import has_three_elements,is_a_greeting

@ddt

class FooTestCase(unittest.TestCase):

@file_data('test_data_dict.json')

def test_file_data_json_dict(self, value):

self.assertTrue(has_three_elements(value))

@file_data('test_data_list.json')

def test_file_data_json_list(self, value):

self.assertTrue(is_a_greeting(value))

if __name__=='__main__':

unittest.main(verbosity=2

使用yaml文件

import unittest

from ddt import ddt, file_data

from ddt_demo.mycode import has_three_elements,is_a_greeting

@ddt

class FooTestCase(unittest.TestCase):

@file_data('test_data_dict.yaml')

def test_file_data_yaml_dict(self, value):

self.assertTrue(has_three_elements(value))

@file_data('test_data_list.yaml')

def test_file_data_yaml_list(self, value):

self.assertTrue(is_a_greeting(value))

if __name__=='__main__':

unittest.main(verbosity=2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值