我正在修改使用我们的单元测试规范进行设置,如
在场景Y中发生行为X时的SUT规范 鉴于这件事 还有另一件事 当我做X ... 那应该做...... 它也应该......
我在Actions中包含了GivenThat的每个步骤...任何反馈是否与Actions分离是好/坏/或更好的方式使GivenThat清楚?
/// <summary>
/// Given a product is setup for injection
/// And Product Image Factory Is Stubbed();
/// And Product Size Is Stubbed();
/// And Drawing Scale Is Stubbed();
/// And Product Type Is Stubbed();
/// </summary>
protected override void GivenThat()
{
base.GivenThat();
Action givenThatAProductIsSetupforInjection = () =>
{
var randomGenerator = new RandomGenerator();
this.Position = randomGenerator.Generate<Point>();
this.Product = new Diffuser
{
Size =
new RectangularProductSize(
2.Inches()),
Position = this.Position,
ProductType =
Dep<IProductType>()
};
};
Action andProductImageFactoryIsStubbed = () => Dep<IProductBitmapImageFactory>().Stub(f => f.GetInstance(Dep<IProductType>())).Return(ExpectedBitmapImage);
Action andProductSizeIsStubbed = () =>
{
Stub<IDisplacementProduct, IProductSize>(p => p.Size);
var productBounds = new ProductBounds(Width.Feet(), Height.Feet());
Dep<IProductSize>().Stub(s => s.Bounds).Return(productBounds);
};
Action andDrawingScaleIsStubbed = () => Dep<IDrawingScale>().Stub(s => s.PixelsPerFoot).Return(PixelsPerFoot);
Action andProductTypeIsStubbed = () => Stub<IDisplacementProduct, IProductType>(p => p.ProductType);
givenThatAProductIsSetupforInjection();
andProductImageFactoryIsStubbed();
andProductSizeIsStubbed();
andDrawingScaleIsStubbed();
andProductTypeIsStubbed();
}
答案 0 :(得分:2)
将它们放在不同的方法中,以便您可以在其他方式中组合它们。另外,使用下划线代替空格(而不是驼峰)。另外,创建一个方法Given_that
,其中包含Action
个代表的参数。
protected void Given_that(params Action[] preconditions)
{
foreach (var action in preconditions)
{
action();
}
}
...
protected void a_product_is_set_up_for_injection()
{
...
}
protected void product_image_factory_is_stubbed()
{
...
}
etc...
...
Given_that(a_product_is_set_up_for_injection,
product_image_factory_is_stubbed,
product_size_is_stubbed,
drawing_scale_is_stubbed,
product_type_is_stubbed);
话虽这么说,我认为你的先决条件的命名不是BDD。它们本质上是技术性的,并不表示业务需求。如果你要告诉一个非程序员你正在测试什么,你可能不会说“该产品是用于注射的。”你更可能会说
Given a displacement product
that is a two inch rectangular diffuser
that has a random position
that has a bitmap
that has a size bounded by feet
that has the expected pixels per foot
现在你可以用很少的重复来编写你的“给定”方法:
protected [the type of your test class] Given(params Action given)
{
given();
return this;
}
protected void That(params Action[] preconditions)
{
foreach (var precondition in preconditions)
{
precondition();
}
}
Given(a_displacement_product)
.That(is_a_two_inch_rectangular_diffuser,
has_a_random_position,
has_a_bitmap,
has_a_size_bounded_by_feet,
has_the_expected_pixels_per_foot);
答案 1 :(得分:1)
在单独的方法中编写 Givens , Whens 和 Thens 是一个好主意,它就像实例 SpecFlow (http://www.specflow.org)做到了。因此,如果想要一些自动化来创建那些无聊的重复管道,我真的会建议使用像SpecFlow这样的工具。作为奖励,您将获得一个很好的报告工具:)
使代码更流畅的另一个选择是制作一个小的BDD基类。在GitHub上看看Jonas Follesoe的精彩小BDD DSL:http://gist.github.com/406014;
public abstract class BDD<T> where T : BDD<T>
{
protected T Given { get { return (T)this; } }
protected T And { get { return (T)this; } }
protected T When { get { return (T)this; } }
protected T Then { get { return (T)this; } }
}
正如迈克尔梅多斯在他的回答中指出的那样;如果您采用BDD方式进行TDD(您确实应该这样做),请继续专注于让您的商务人士可以阅读。那意味着;远离技术措辞模拟,注入,工厂,例外等。