自动化测试用例写多了,不可避免会遇到这个问题,每次运行无需运行所有的用例,那么如何把要运行的用例挑出来并高效组织它们呢?
一般说来,通用的做法都是
把要运行的用例用特殊标记Mark出来,然后框架运行时,自动寻找这些带标记的case,并把它们装到一个新的test suite里。
所以高效组织测试用例的关键就是两部分:
1. 如何标记待测试用例.
2. 运行时如何收集这些带标记的用例。
以下列出来我经历过的方法:
1.给所有的测试用例编号,把测试用例按照 编号, summary, Path, ClassName, 测试运行与否的flag等等,写到一个外部文件里,通常是Excel,
每次测试框架运行时,先去这个文件里,一行一行的读文件,如果发现“测试运行与否的flag”的值是True, 就把这条case拿出来放到一个临时变量里,读完整个文件,就拿到了
所有要运行的case, 这个时候,导入这个case需要的所有依赖,运行这个case,并把运行结果写回到一个results的文件里。 那么,改动老的case,增加新的case,怎么办呢?
勤快一点的,每写一个/更改一个自动化用例,手工更新这个外部表格。 懒一点的,写一段代码,每写/改一个case,手工运行这段代码,把更改写进去。
2.利用装饰器,经典的如TestNG,可以在测试用例前加@BeforeSuite, 今天要讲的也是这个。如何在python里实现。
先说下思想: 我期望自动化测试运行时候,可以根据我提供的不同的tag,运行不同的测试用例。 前提是我写自动化用例的时需给每个测试用例,都加上tag并赋值。
在运行时候,框架通过我提供的不同的tag,去找这些被标记的case,然后组织起来运行。
要实现这个,我们需要接收用户参数,可以用:
1.sys.argv[1:]来自己写代码处理,也可以用标准库argparse来,我们用后者。
argparse 的用法很直观, 先看段代码::
|
|
这个时候,如在command line里输入
使用argparse就可以方便的获取用户参数,并处理。关于argparse的用法,请参考官网。
2.用户输入的参数我们接收处理了,那么如何处理这些tag呢,这就要用到装饰器:
|
|
上面的代码呢,我们定义了一个装饰器,这个装饰器唯一的作用,是接收传入的类,然后给这些类增加一些属性,这些属性后续用来判断是否要执行。 使用时在新建立测试类上加上@Testcase即可。
3.测试用例类,这些测试类或者测试类中的函数实现了一个个的功能。
|
|
我们可以利用装饰器里的tag参数, enable参数来实现测试用例的筛选。
4.我们再定义一个类,这个类作为一个test case的执行器,把要运行的测试用例装进来,并发,或者顺序执行。
|
|
5.利用threading.Semaphore实现线程并发限制。
6.实现:
|
|
这里重点讲下标记为
我们使用了反射机制
反射: 有时候我们会碰到这样的需求,需要执行对象的某个方法,或是需要对对象的某个字段赋值,而方法名或是字段名在编码代码时并不能确定,需要通过参数传递字符串的形式输入。举个具体的例子:当我们需要实现一个通用的DBM框架时,可能需要对数据对象的字段赋值,但我们无法预知用到这个框架的数据对象都有些什么字段,换言之,我们在写框架的时候需要通过某种机制访问未知的属性。这个机制被称为反射(反过来让对象告诉我们他是什么),或是自省
dir([obj]):
调用这个方法将返回包含obj大多数属性名的列表(会有一些特殊的属性不包含在内)。obj的默认值是当前的模块对象。hasattr(obj, attr):
这个方法用于检查obj是否有一个名为attr的值的属性,返回一个布尔值。getattr(obj, attr):
调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为’bar’,则返回obj.bar。
对于所有的测试类,我们会逐个把他们导入(示例里无这段代码,关于case class的导入可以根据 -target这个参数的值来代码实现,此处未展示。)
对于每一个类,我们通过dir(), getattr()拿到测试类所有的可用方法,然后这些方法因为有装饰器TestCase的加持,我们可以顺利的根据参数-tags拿到要运行的测试用例。
然后我们根据拿到的每一个测试用例,判断它们是否有需要的属性( enabled,type), 然后对于每个有这个属性的用例,我们在放到真正运行的测试用例list里。
最后对测试用例list的用例,每一个都放入TestExecutor里执行,TestExecutor 实现了多线程及多线程限制。
我们来看下运行效果:
输入:
python Android/init.py -target test -tag smoke -n 3
输出:
因为我们限制了并发线程数为2, 所以我们先看到以下输出。
5秒后,又看到如下:
如此一来,我们仅需要写测试用例时,添加合适的tag,然后运行时用参数区分,就可以不修改代码的的情况下运行不同的case了。