一个很小的框架,使得用python编写测试数据生成器变得很容易
make-it-eas的Python项目详细描述
简介
make it easy是一个很小的框架,它使用python编写测试数据生成器变得很容易。 框架是Java make-it-easy by Nat Pryce
的端口测试数据构建器在面向对象软件中描述,由 史蒂夫·弗里曼和纳特·普赖斯。这个库允许您编写测试数据构建器,而重复性和 样板代码比书中描述的方法。
安装
可以使用常用的python打包工具轻松安装。这取决于 分发,但只要在安装时有网络连接, 安装过程会帮你搞定的。
用法
basic
考虑下面的类层次结构。这个层次结构说明了一些复杂的因素: 抽象基类的结果,并且有一个属性(成熟度)不是通过构造函数设置的,而是通过 水果班的作业。
classFruit(object):def__init__(self):self._ripeness=0.0defripen(self,ripeness):self._ripeness=ripeness@propertydefis_ripe(self):returnself._ripeness>=0.9classApple(Fruit):def__init__(self,num_of_leaves):super(Apple,self).__init__()self.num_of_leaves=num_of_leavesclassBanana(Fruit):def__init__(self,curve):super(Banana,self).__init__()self.curve=curve
按照不断增长的面向对象软件中记录的风格,在测试的指导下这样做会像这样:
classAppleBuilder(object):def__init__(self):self._ripeness=0.5self._leaves=2defwith_ripeness(self,ripeness):self._ripeness=ripenessreturnselfdefwith_leaves(self,leaves):self._leaves=leavesreturnselfdefbut(self):returnAppleBuilder() \ .with_ripeness(self._ripeness) \ .with_leaves(self._leaves)defbuild(self):apple=Apple(self._leaves)apple.ripen(self._ripeness)returnappleclassBananaBuilder(object):def__init__(self):self._ripeness=0.5self._curve=0.1defwith_ripeness(self,ripeness):self._ripeness=ripenessdefwith_curve(self,curve):self._curve=curvedefbut(self):returnBananaBuilder() \ .with_ripeness(self._ripeness) \ .with_curve(self._curve)defbuild(self):banana=Banana()banana.ripen(self._ripeness)banana.curve=self._curvereturnbananaapple_with_two_leaves=AppleBuilder().with_leaves(2)ripe_apple=apple_with_two_leaves.but().with_ripeness(0.95)unripe_apple=apple_with_two_leaves.but().with_ripeness(0.1)apple1=ripe_apple.build()apple2=unripe_apple.build()
使用“使事情变得简单”时,可以做到以下几点:
frommake_it_easyimport*defapple(leaves=2,ripeness=0.0):an_apple=Apple(leaves)an_apple.ripen(ripeness)returnan_appledefbanana(curve=0.1,ripeness=0.0):a_banana=Banana(curve)a_banana.ripen(ripeness)returna_bananaapple_with_two_leaves=an(apple,with_(2,'leaves'))ripe_apple=apple_with_two_leaves.but(with_(0.95,'ripeness'))unripe_apple=apple_with_two_leaves.but().with_(0.1,'ripeness'))apple1=make(ripe_apple)apple2=make(unripe_apple)
如您所见,使用make-it-easy,您必须编写更少的重复和样板代码。
价值捐赠者
原语/标记
值的提供者是任何原语('bob'/3/false/etc.)或aMaker
(a,an函数返回的对象)。
所有这些都可以用作with_
中的值。例如,客户Maker
可以按Maker
顺序成为捐赠者。是的
重要的是要注意,如果将Maker
用作供者,则每次都将创建一个新实例:
a_customer=a(customer,with_('Bob',as_('name')))an_order=an(order,with_(a_customer,as_('customer')))my_order1=make(an_order)my_order2=make(an_order)assert_that(my_order1.customer,is_(instance_of(Customer)))assert_that(my_order2.customer,is_(instance_of(Customer)))assert_that(my_order1.customer,is_not(same_instance(my_order2.customer)))# two different instances!!!
同值供体
有时在创建新数据对象时需要共享相同的值,这可以使用the_same
值来完成
捐赠者。在下面的示例中,“我的订单1”和“我的订单2”将具有相同的客户实例:
a_customer=a(customer,with_('Bob',as_('name')))an_order=an(order,with_(the_same(a_customer),as_('customer')))my_order1=make(an_order)my_order2=make(an_order)assert_that(my_order1.customer,is_(same_instance(my_order2.customer)))
定制捐赠者
为了创建自定义的捐助程序,您只需要实现Donor
接口。
classIndexDonor(Donor):def__init__(self):self._count=itertools.count()@propertydefvalue(self):returnnext(self._count)an_indexed_thing=an(an_indexed_thing,with_(IndexDonor(),as_('index')))indexed_thing1=make(an_indexed_thing)indexed_thing2=make(an_indexed_thing)assert_that(indexed_thing1.index,is_(equal_to(0)))assert_that(indexed_thing2.index,is_(equal_to(1)))
序列供体
有时我们希望从序列中分配值,这样我们就可以预测它们的值或了解数据的位置 来自测试诊断。使用“使其简单化”可以定义固定或重复的值序列。
固定序列由from_
函数定义,该函数需要一个iterable:
letters=from_("abc")assert_that(letters.value,is_(equal_to("a")))assert_that(letters.value,is_(equal_to("b")))assert_that(letters.value,is_(equal_to("c")))
如果要求固定值序列提供的元素多于创建序列时指定的元素,则固定值序列将失败。 当所有元素耗尽时,重复序列将从序列的开头开始:
letters=from_repeating("ab")assert_that(letters.value,is_(equal_to("a")))assert_that(letters.value,is_(equal_to("b")))assert_that(letters.value,is_(equal_to("a")))assert_that(letters.value,is_(equal_to("b")))assert_that(letters.value,is_(equal_to("a")))assert_that(letters.value,is_(equal_to("b")))
固定序列和重复序列都可以从任何iterable(tuple/list/set/dict/etc)创建。
计算序列
如果我们不想显式地指定一系列值,我们可以使用一些方便的基类来帮助我们
计算序列中的每个元素。
IndexedSequence
从整数索引计算序列中的每个元素,从零开始。
classFTagSequence(IndexedSequence):def_value_at(self,index):return'f'+"'"*indexf_tag_sequence=FTagSequence()assert_that(f_tag_sequence.value,is_(equal_to("f")))assert_that(f_tag_sequence.value,is_(equal_to("f'")))assert_that(f_tag_sequence.value,is_(equal_to("f''")))
chainedsequence根据序列前面的元素计算序列中的每个元素。
classFTagChainedSequence(ChainedSequence):def_first_value(self):return'f'def_value_after(self,prev_value):returnprev_value+"'"f_tag_sequence=FTagChainedSequence()assert_that(f_tag_sequence.value,is_(equal_to("f")))assert_that(f_tag_sequence.value,is_(equal_to("f'")))assert_that(f_tag_sequence.value,is_(equal_to("f''")))