C# &引用;“你好,世界”TDD方式?
自从我被介绍给TDD以来,我一直在思考这个问题。 构建“Hello World”应用程序的最佳方法是什么?它将使用测试驱动开发在控制台上打印“Hello World” 我的测试是什么样的?什么课程C# &引用;“你好,世界”TDD方式?,c#,unit-testing,tdd,nunit,C#,Unit Testing,Tdd,Nunit,自从我被介绍给TDD以来,我一直在思考这个问题。 构建“Hello World”应用程序的最佳方法是什么?它将使用测试驱动开发在控制台上打印“Hello World” 我的测试是什么样的?什么课程 请求:没有指向TDD的“类似维基百科”链接,我对TDD很熟悉。只是好奇如何解决这个问题 我猜是这样的: using NUnit.Framework; using System.Diagnostics; [TestFixture] public class MyTestClass { [Tes
请求:没有指向TDD的“类似维基百科”链接,我对TDD很熟悉。只是好奇如何解决这个问题 我猜是这样的:
using NUnit.Framework;
using System.Diagnostics;
[TestFixture]
public class MyTestClass {
[Test]
public void SayHello() {
string greet = "Hello World!";
Debug.WriteLine(greet);
Assert.AreEqual("Hello World!", greet);
}
}
public class my_program
{
Iconsole _consol;
public my_program(Iconsole consol)
{
if (consol != null)
_consol = consol;
}
public void greet()
{
_consol.WriteToConsole("Hello world");
}
}
嗯……我还没看过TDD版的hello world。但是,要想看到一个类似于TDD和可管理性的简单问题,您可以看看()。至少这会让你看到你在hello world中可能达到的过度工程化程度。演示者视图?(模型似乎并非绝对必要) 视图将是一个将输出传递到控制台的类(简单的单行方法) Presenter是调用view.ShowText(“Hello World”)的接口,您可以通过提供存根视图来测试这一点 但是为了提高效率,我只需要编写这个该死的程序:) 一次测试就足够了(在伪代码中):
IView view=Stub();
Expect(view.ShowText(“helloworld”);
演示者p=新演示者(视图);
p、 Show();
Assert.IsTrue(view.methodscaled);
在java中,您可以捕获System.out流(“重定向”)并读取其内容。我相信C#也可以做到这一点。java中只有几行代码,所以我相信C#伪代码中的代码不会太多:
- 创建一个接受流的模拟对象
- 通过某种依赖项注入(如构造函数参数)将helloworld调用到此模拟上李>
- 验证“Hello World”字符串是否已流式传输到模拟中
- 在组件如何与其他东西交互方面定义您的成功标准,而不仅仅是它如何与您交互。TDD关注外部行为
- 设置环境(mock)以处理事件链
- 运行它
- 核实
[TestMethod]
public void HelloWorld_WritesHelloWorldToConsole()
{
// Arrange
IConsole consoleMock = MockRepository.CreateMock<IConsole>();
// primitive injection of the console
Program.Console = consoleMock;
// Act
Program.HelloWorld();
// Assert
consoleMock.AssertWasCalled(x => x.WriteLine("Hello World"));
}
重构到更有用的东西;-) 一个非常有趣的问题。我不是一个巨大的TDD用户,但我会抛出一些想法 我假设您要测试的应用程序如下:
public static void Main()
{
Console.WriteLine("Hello World");
}
现在,由于我想不出任何好的直接测试方法,我将把编写任务分解成一个接口
public interface IOutputWriter
{
void WriteLine(string line);
}
public class ConsoleWriter : IOutputWriter
{
public void WriteLine(string line)
{
Console.WriteLine(line);
}
}
然后像这样分解应用程序
public static void Main()
{
IOutputWriter consoleOut = new ConsoleWriter();
WriteHelloWorldToOutput(consoleOut);
}
public static void WriteHelloWorldToOutput(IOutputWriter output)
{
output.WriteLine("Hello World");
}
现在,您有了一个方法的注入点,该注入点允许您使用所选的模拟框架断言WriteLine方法是使用“Hello World”参数调用的
我没有解决的问题(我对输入感兴趣):
我真的不得不反对这个问题!所有的方法都有自己的位置,TDD在很多地方都很好。但是用户界面是我真正放弃TDD的第一个地方。在我看来,这是MVC设计模式的最佳证明之一:以编程方式测试模型和控制器;目视检查您的视图。您所说的是硬编码数据“Hello World”,并测试它是否能够进入控制台。要在同一源语言中执行此测试,您几乎必须虚拟console对象,它是唯一一个执行任何操作的对象 或者,您可以在bash中编写测试脚本:
echo `java HelloWorldProgram`|grep -c "^Hello World$"
添加到JUnit测试套件有点困难,但有些事情告诉我,这从来都不是计划……我同意David Berger的观点;分离接口,并测试模型。本例中的“model”似乎是一个返回“Hello,world!”的简单类。测试如下所示(在Java中):
我已经写了一篇关于解决
Hello World
TDD风格的文章。假设你了解单元测试,并且理解TDD“红-绿重构过程”(因为你说你熟悉TDD),我会很快解释一个典型的TDD思维过程
如果您考虑一个特定的问题单元,那么您的TDD生活将变得容易得多,并且所有其他相关的事情都应该根据依赖性来考虑。这是一个样本
情景:-
我希望我的程序在控制台上显示hello world
tdd思维过程:-
“我想我的程序将开始运行,然后调用控制台程序将我的消息传递给它,然后我希望我的控制台程序将其显示在屏幕上”
所以我需要测试一下,当我运行我的程序时,它应该调用控制台程序
“现在什么是依赖项?嗯,我知道控制台程序就是其中之一。我不需要担心控制台如何将消息发送到屏幕上(调用io设备、打印等)我只需要知道我的程序成功地调用了控制台程序。我需要相信控制台程序能够正常工作,如果不能正常工作,那么目前我不负责测试和确保它正常工作。我想测试的责任是,我的程序在启动时调用控制台程序。”
“但我甚至不知道要调用什么控制台程序。我知道System.console.Writeline(具体实现),但这可能会在将来因更改而改变
echo `java HelloWorldProgram`|grep -c "^Hello World$"
Greeter greeter = new Greeter();
assertEquals("Hello World!", greeter.greet());
public interface Iconsole
{
void WriteToConsole(string msg);
}
public class FakeConsole : Iconsole
{
public bool IsCalled = false;
public void WriteToConsole(string msg)
{
IsCalled = true;
}
}
var console = new FakeConsole();
console.IsCalled = false;
my_program program = new my_program(console);
program.greet();
public class my_program
{
Iconsole _consol;
public my_program(Iconsole consol)
{
if (consol != null)
_consol = consol;
}
public void greet()
{
_consol.WriteToConsole("Hello world");
}
}
[TestMethod]
public void myProgramShouldDisplayHelloWorldToTheConsole()
{
//arrange
var console = new FakeConsole();
console.IsCalled = false;
my_program program = new my_program(console);
//act
program.greet();
//assert
Assert.AreEqual(true, console.IsCalled, " console was not called to display the greeting");
}