Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# TDD交通信号灯的重构阶段-如何做到这一点?_C#_Java_Unit Testing_Tdd - Fatal编程技术网

C# TDD交通信号灯的重构阶段-如何做到这一点?

C# TDD交通信号灯的重构阶段-如何做到这一点?,c#,java,unit-testing,tdd,C#,Java,Unit Testing,Tdd,因此,我对即将诞生的一个类板进行了以下测试: [TestMethod] public void Set_The_Origin_As_Violet_And_The_Query_Confirms_It() { Board board = new Board(10, 10); Color expected = Color.Violet; board.SetColorAt(0, 0, expected); Color actual = board.GetColorAt(

因此,我对即将诞生的一个类
进行了以下测试:

[TestMethod]
public void Set_The_Origin_As_Violet_And_The_Query_Confirms_It() {
    Board board = new Board(10, 10);

    Color expected = Color.Violet;
    board.SetColorAt(0, 0, expected);
    Color actual = board.GetColorAt(0, 0);
    Assert.AreEqual(expected, actual);
}
我试着运行代码,但编译器表示
Board
不存在。所以我创造了它

我试图再次运行代码,但没有效果,因为SetColorAt()和GetColorAt()方法都不存在。我创造了它们:

public void SetColorAt(int x, int y, Color color) {
}

public void GetColorAt(int x, int y) {
}
不过,并不是每件事都很好,因为我必须把颜色改成紫色。所以我将GetColorAt()改为

所以我第一次得到了绿灯

我希望我的最终代码出现在课程板上的形式如下:

public class Board
{
    private Color[,] board;

    public Board(int x, int y)
    {
        board = new Color[x, y];
    }

    public void SetColorAt(int x, int y, Color color) {
        board[x, y] = color;
    }

    public Color GetColorAt(int x, int y) {
        return board[x, y];
    }
}
我的第一个问题是。。。。 怎么去那里?我能在上面所示的单元测试的“重构”阶段中考虑到,当删除重复时,我最终会得到这个代码吗? 如果答案是肯定的,我觉得我的单元测试是在测试一些过于“本地化”的代码。你看,测试只是检查一个像素和一种颜色,而代码本身要复杂和丰富得多

也许解决方案是增加更多的单元测试?你建议做什么

我的第二个问题是。。。 我知道以后我会想要一个
IBoard
。我应该在上面的单元测试中表达这一点吗?我应该让他去吗

Board board = new Board(10, 10);
按原样创建
IBoard
界面?如何应对

public void GetColorAt(int x, int y) {
    return Color.Violet;
}
这里的return Color.Violet语句可以被视为数据重复,因此您可以重构这一部分。不过,最简单的方法是在调用SetColorAt时设置一个单色值

public class Board
{
    private Color theColor;

    public Board(int x, int y)
    {
    }

    public void SetColorAt(int x, int y, Color color) {
        theColor = color;
    }

    public Color GetColorAt(int x, int y) {
        return theColor;
    }
}

现在,您需要进行更多的测试,以显示您可以将单独的单元格设置为不同的颜色。

您熟悉测试模式,对吗?你的测试就是这么做的

[TestMethod]
public void Set_The_Origin_As_Violet_And_The_Query_Confirms_It() {
    // Arrange
    Board board = new Board(10, 10);
    // Act
    board.SetColorAt(0, 0, expected);
    // Assert
    Color expected = Color.Violet;
    Assert.AreEqual(expected, board.GetColorAt(0, 0));
}
我喜欢使用稍微修改过的表单,arrangeassertnotact-Assert。我们的想法是验证行为本身是导致我们测试的条件的原因,因为我们在行为之前断言我们的条件不满足。下面是它的外观:

[TestMethod]
public void Set_The_Origin_As_Violet_And_The_Query_Confirms_It() {
    // Arrange
    Board board = new Board(10, 10);
    // Assert
    Color expected = Color.Violet;
    Assert.AreNotEqual(expected, board.GetColorAt(0, 0));
    // Act
    board.SetColorAt(0, 0, expected);
    // Assert
    Assert.AreEqual(expected, board.GetColorAt(0, 0));
}

这迫使您在第一次编写稍微不那么简单的实现。您仍然需要额外的测试来驱动GetColorAt()的完整实现;为此,我喜欢认为,编写完整实现的时候,要比在另一种特殊情况下(我想,对于这个应用程序,大概是N=3左右)假装的麻烦少一些。

从您想要实现的内容的高级描述开始

  • 有行和列的正方形板
  • 每个董事会职位都应该有一个 颜色
  • 董事会用户应该能够 设置特定板的颜色 位置(像素)
  • 董事会用户应 能够得到一张照片的颜色 具体董事会位置
  • 等等
接下来,使用小测试来驱动实现。有时从边界条件开始比较容易

When asked to get the color at a specific board position
- given a default board, and
  - the row value is less than zero
  - should throw argument exception

When asked to get the color at a specific board position
- given a default board, and
  - the row value is greater than the highest board row
  - should throw argument exception
“行值大于最高的线路板行”强制您以某种方式设置最高的线路板行。测试并不关心您是通过构造函数还是属性设置器来设置它

When constructed with board dimensions
 - should set the highest board row
“应设置最高的线路板行”强制您以某种方式访问已设置的值。也许是一个属性获取者

When asked to get the color at a specific board position
- given a default board, and
  - the column value is less than zero
  - should throw argument exception

When asked to get the color at a specific board position
- given a default board, and
  - the column value is greater than the highest board column
  - should throw argument exception
“列值大于最高的board列”强制您为最高的列复制最高的行解决方案

When constructed with board dimensions
 - should set the highest board column
等等

“应返回默认颜色”强制您在某处显示默认颜色。这不应该是只有测试才知道的神奇值。将其公开为板上的常量或只读值

When asked to get the color at a specific board position
- given a default board, and
  - the row value is within the board space, and
  - the column is within the board space, and
  - the requested position has a known color
  - should return the color of the board at the requested position
“请求的位置具有已知颜色”强制您建立设置板位置颜色的能力。您现在可以这样做,因为您在某个位置获取颜色的测试失败。所以把它放在一边,建立起二传手

When asked to SET the color at a specific board position
- given a default board, and
  - the row value is less than zero
  - should throw argument exception

When asked to set the color at a specific board position
- given a default board, and
  - the row value is greater than the highest board row
  - should throw argument exception

When asked to set the color at a specific board position
- given a default board, and
  - the column value is less than zero
  - should throw argument exception

When asked to set the color at a specific board position
- given a default board, and
  - the column value is greater than the highest board column
  - should throw argument exception

When asked to set the color at a specific board position
- given a default board, and
  - the row value is within the board space, and
  - the column is within the board space
  - should set the color at the given position to the requested color
“应将给定位置的颜色设置为请求的颜色”使用get实现验证值设置是否正确。一旦您正确地实现了它,您的所有测试将再次变为绿色

只需继续构建附加功能,一次只构建一小部分


当您使用与实现无关的术语进行测试时,您可以将实现更改为使用IBoard或Ruby或其他任何东西,并且测试描述不必更改。您必须更改一些测试实施细节,但测试的既定目标不必更改。

我认为您编写了一个设置颜色并获得颜色的电路板,这是一次冒险。是什么驱动了一块木板?什么需要一块板来存储颜色?黑板是颜色的存储库

董事会有太多的实施细节。看,颜色是另一个对象的属性。你真的关心电路板存储颜色还是存储这个具有颜色属性的域对象。如果以后您也存储了董事会职位的历史记录,该怎么办。然后你要用两块板,一块是彩色板,然后是历史板

您确实需要将存储机制从实际依赖特定类型的颜色(紫色、蓝色、绿色等)中抽象出来

从理解问题域开始的问题是,它会将您的设计归档。而且它也不会如此强大

对我来说,我会从一个问题开始:颜色是什么域对象的属性?那么我的测试就会生成这个域对象。据我所知,域对象可能存在于板中,也可能不存在于板中


希望这对您有所帮助。

问题在于您从“这是正确的解决方案”开始。TDD是一种引导你做出好设计的技术,而不是预先确定的。我明白你的意思。但我想不出除了这个以外还有什么别的解决办法。您有一组(x,y)点,并且希望将它们存储在二维阵列中。这是实现t的最简单方法
When asked to get the color at a specific board position
- given a default board, and
  - the row value is within the board space, and
  - the column is within the board space, and
  - the requested position has a known color
  - should return the color of the board at the requested position
When asked to SET the color at a specific board position
- given a default board, and
  - the row value is less than zero
  - should throw argument exception

When asked to set the color at a specific board position
- given a default board, and
  - the row value is greater than the highest board row
  - should throw argument exception

When asked to set the color at a specific board position
- given a default board, and
  - the column value is less than zero
  - should throw argument exception

When asked to set the color at a specific board position
- given a default board, and
  - the column value is greater than the highest board column
  - should throw argument exception

When asked to set the color at a specific board position
- given a default board, and
  - the row value is within the board space, and
  - the column is within the board space
  - should set the color at the given position to the requested color