我如何构建和扩展应用程序开发和测试

从简单地开始开发,通过使用一个元素编写和测试你的代码,然后将其扩展到多个。
65 位读者喜欢这篇文章。
Security monster

在我的上一篇文章中,我解释了为什么一次性解决编码问题,就像面对僵尸群一样,是一个错误。我还解释了第一个 ZOMBIES 原则,Zero(零)。在本文中,我将演示接下来的两个原则:One(一)和 Many(多)。

ZOMBIES 是一个首字母缩略词,代表

Z – Zero(零)

O – One(一)

M – Many(多,或更复杂)

B – 边界行为

I – 接口定义

E – 练习异常行为

S – 简单场景,简单解决方案

在上一篇文章中,你实现了 Zero(零),它提供了通过代码的最简单路径。绝对没有任何条件处理逻辑。现在是时候进入 One(一)了。

Zero(零)不同,它基本上意味着没有添加任何内容,或者我们有一个空案例,没有什么需要处理的,One(一)意味着我们有一个单一的案例需要处理。这个单一的案例可能是一个集合中的一个项目,或者一个访问者,或者一个需要特殊处理的事件。

使用 Many(多),我们现在处理的是可能更复杂的情况。集合中的两个或多个项目,两个或多个需要特殊处理的事件,等等。

One(一)的实践

通过向你的虚拟购物车中添加一些东西,在上一篇文章的代码基础上构建。首先,编写一个伪造的测试

[Fact]
public void Add1ItemBasketHas1Item() {
	var expectedNoOfItems = 1;
	var actualNoOfItems = 0;
	Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

正如预期的那样,此测试失败,因为你硬编码了一个不正确的值

Starting test execution, please wait...

A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.57] tests.UnitTest1.NewlyCreatedBasketHas0Items [FAIL]
  X tests.UnitTest1.NewlyCreatedBasketHas0Items [4ms]
  Error Message:
   Assert.Equal() Failure
Expected: 0
Actual: 1 
[...]

现在是时候考虑如何停止伪造了。你已经创建了一个购物车的实现(一个用于保存项目的 ArrayList)。但是你如何实现一个项目呢?

简单性应该始终是你的指导原则,并且在不太了解实际项目的情况下,你可以通过将其实现为另一个集合来稍微伪造一下。该集合可以包含什么?嗯,因为你主要对计算购物车总额感兴趣,所以项目集合至少应包含价格(以任何货币,但为简单起见,使用美元)。

一个简单的集合可以保存项目的 ID(指向项目的指针,该项目可能保存在系统上的其他位置)以及项目的关联价格。

一个可以轻松捕获此信息的良好数据结构是键/值结构。在 C# 中,首先想到的是 Hashtable

在应用程序代码中,向 IShoppingAPI 接口添加新功能

int AddItem(Hashtable item);

这个新功能接受一个项目(Hashtable 的一个实例)并返回在购物车中找到的项目数。

在你的测试中,将硬编码的值替换为对接口的调用

[Fact]
public void Add1ItemBasketHas1Item() {            
    var expectedNoOfItems = 1;
    Hashtable item = new Hashtable();
    var actualNoOfItems = shoppingAPI.AddItem(item);
    Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

此代码实例化 Hashtable 并将其命名为 item,然后在购物接口上调用 AddItem(item),这将返回购物车中的实际项目数。

要实现它,请转向 ShoppingAPI

public int AddItem(Hashtable item) {
    return 0;
}

你再次伪造它,只是为了查看你的测试结果(它们是你代码的第一个客户)。如果测试失败(正如预期的那样),请将硬编码的值替换为实际代码

public int AddItem(Hashtable item) {
    basket.Add(item);
    return basket.Count;
}

在工作代码中,向购物车添加一个项目,然后返回购物车中项目的计数

Test Run Successful.
Total tests: 2
     Passed: 2
 Total time: 1.0633 Seconds

所以现在你有两个测试通过了,并且几乎涵盖了 Z(零)和 O(一),ZOMBIES 的前两部分。

片刻的反思

如果你回顾一下到目前为止所做的工作,你会注意到,通过将注意力集中在处理最简单的 Zero(零)和 One(一)场景上,你已经设法创建了一个接口,并定义了一些处理逻辑边界!这不是很棒吗?你现在已经部分实现了最重要的抽象,并且你知道如何处理未添加任何内容以及添加了一件事的情况。并且由于你正在构建一个电子商务 API,因此你当然不会预见到任何其他会限制你的客户购物的边界。你的虚拟购物车在所有意图和目的上都是无限的。

ZOMBIES 提供的逐步改进的另一个重要(虽然不一定立即显而易见)方面是不愿意头脑发热地投入到实现的荆棘中。你可能已经注意到,这对于实现任何东西是多么的羞怯。对于初学者来说,最好通过硬编码值来伪造实现。只有在你看到接口以明智的方式与你的测试交互后,你才愿意卷起袖子并加强实现代码。

但即使那样,你也应该始终首选简单、直接的构造。并努力尽可能避免条件逻辑。

Many(多)的实践

通过定义当客户向购物车添加两个项目时的期望来扩展你的应用程序。第一个测试是伪造的。它期望 2,但通过硬编码 0 个项目来强制它失败

[Fact]
public void Add2ItemsBasketHas2Items() {
	var expectedNoOfItems = 2;
	var actualNoOfItems = 0;
	Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

当你运行测试时,其中两个通过成功(之前的两个,Z(零)和 O(一)测试),但正如预期的那样,硬编码的测试失败了

A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.57] tests.UnitTest1.Add2ItemsBasketHas2Items [FAIL]
  X tests.UnitTest1.Add2ItemsBasketHas2Items [2ms]
  Error Message:
   Assert.Equal() Failure
Expected: 2
Actual: 0

Test Run Failed.
Tatal tests: 3
     Passed: 2
     Failed: 1

将硬编码的值替换为对应用程序代码的调用

[Fact]
public void Add2ItemsBasketHas2Items() {
	var expectedNoOfItems = 2;
	Hashtable item = new Hashtable();
	shoppingAPI.AddItem(item);
	var actualNoOfItems = shoppingAPI.AddItem(item);
	Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

在测试中,你添加了两个项目(实际上,你添加了相同的项目两次),然后将预期项目数与在第二次添加项目后来自 shoppingAPI 实例的项目数进行比较。

现在所有测试都通过了!

敬请关注

你现在已经完成了等式 ZOM 部分的第一遍。你对 Zero(零)、One(一)和 Many(多)进行了遍历。在下一篇文章中,我将看看 BI。保持警惕!

接下来阅读什么
标签
User profile image.
自 1990 年以来,Alex 一直从事软件开发。他目前的热情是如何将“软”带回软件中。他坚信,我们的行业已经达到了一个高度,可以完全实现这个崇高的目标(即将“软”带回软件中)。

评论已关闭。

© . All rights reserved.