Well I have been thinking about this for a while, ever since I was introduced to TDD. Which would be the best way to build a \"Hello World\" application ? which would print \"H
I guess something like this:
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);
}
}
You need to hide the Console behind a interface. (This could be considered to be useful anyway)
Write a Test
[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"));
}
Write the program
public static class Program
{
public static IConsole Console { get; set; }
// method that does the "logic"
public static void HelloWorld()
{
Console.WriteLine("Hello World");
}
// setup real environment
public static void Main()
{
Console = new RealConsoleImplementation();
HelloWorld();
}
}
Refactor to something more useful ;-)
A very interesting question. I'm not a huge TDD user, but I'll throw some thoughts out.
I'll assume that the application that you want to test is this:
public static void Main()
{
Console.WriteLine("Hello World");
}
Now, since I can't think of any good way of testing this directly I'd break out the writing task into an interface.
public interface IOutputWriter
{
void WriteLine(string line);
}
public class ConsoleWriter : IOutputWriter
{
public void WriteLine(string line)
{
Console.WriteLine(line);
}
}
And break the application down like this
public static void Main()
{
IOutputWriter consoleOut = new ConsoleWriter();
WriteHelloWorldToOutput(consoleOut);
}
public static void WriteHelloWorldToOutput(IOutputWriter output)
{
output.WriteLine("Hello World");
}
Now you have an injection point to the method that allows you to use the mocking framework of your choice to assert that the WriteLine method is called with the "Hello World" parameter.
Problems that I have left unsolved (and I'd be interested in input):
How to test the ConsoleWriter class, I guess you still need some UI testing framework to achieve this, and if you had that then the whole problem in moot anyway...
Testing the main method.
Why I feel like I've achieved something by changing one line of untested code into seven lines of code, only one of which is actually tested (though I guess coverage has gone up)
I really have to object to the question! All methodologies have their place, and TDD is good in a lot of places. But user interfaces is the first place I really back off from TDD. This, in my humble opinion is one of the best justifications of the MVC design pattern: test the heck out of your models and controller programmatically; visually inspect your view. What you're talking about is hard-coding the data "Hello World" and testing that it makes it to the console. To do this test in the same source language, you pretty much have to dummy the console object, which is the only object that does anything at all.
Alternately, you can script your test in bash:
echo `java HelloWorldProgram`|grep -c "^Hello World$"
A bit difficult to add to a JUnit test suite, but something tells me that was never the plan....