"Hello World" - The TDD way?

Cóż, myślałem o tym od jakiegoś czasu, odkąd zostałem wprowadzony do TDD. Jaki byłby najlepszy sposób na zbudowanie aplikacji "Hello World"? który wydrukuje "Hello World" na konsoli-używając Test Driven Development.

Jak wyglądałyby moje testy ? a w jakich klasach ?

Request: No "Wikiprojekt " linkuje do tego czym jest TDD, znam TDD. Jestem ciekaw, jak można temu zaradzić.

Author: abhilash, 2009-04-27

10 answers

Musisz ukryć konsolę za interfejsem. (To i tak może być uznane za przydatne)

Napisz 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"));
}

Napisz 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 do czegoś bardziej użytecznego; -)

 20
Author: Stefan Steinegger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 15:21:09

Prezenter-Widok? (model nie wydaje się bezwzględnie konieczny)

View będzie klasą, która przekazuje wyjście do konsoli (proste metody jednoliniowe)

Presenter jest interfejsem wywołującym widok.ShowText ("Hello World"), możesz to przetestować, udostępniając widok początkowy.

Dla produktywności po prostu napisałbym ten cholerny program:)

Pojedynczy test powinien wystarczyć (w pseudokodzie):

IView view = Stub<IView>();
Expect( view.ShowText("Hello World") );

Presenter p = new Presenter( view );
p.Show();

Assert.IsTrue( view.MethodsCalled );
 5
Author: Lennaert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 14:51:49

No cóż...Nie widziałem wersji TDD hello world. Ale, aby zobaczyć podobnie prosty problem, który został potraktowany z TDD i zarządzania w umyśle, można spojrzeć na Enterprise FizzBuzz (kod). Przynajmniej to pozwoli Ci zobaczyć poziom over-inżynierii można ewentualnie osiągnąć w hello world.

 5
Author: dustyburwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 14:53:47

Pseudo-kod:

  • Stwórz makietę czegoś, co akceptuje strumień.
  • wywołanie helloworld na tej makiecie poprzez wstrzyknięcie zależności (jak argument konstruktora).
  • Sprawdź, czy ciąg "Hello World" został przesłany do Twojej makiety.

W kodzie produkcyjnym używasz znaku zachęty zamiast makiety.

Zasada kciuka:

  • Zdefiniuj swoje kryteria sukcesu w jaki sposób komponent współdziała z innymi rzeczami, a nie tylko w jaki sposób współdziała z Tobą. TDD koncentruje się na zewnętrznych zachowaniach.
  • ustawić środowisko (mocks) do obsługi łańcucha zdarzeń.
  • Uruchom go.
  • zweryfikuj.
 4
Author: Tormod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 14:56:32

Bardzo ciekawe pytanie. Nie jestem wielkim użytkownikiem TDD, ale wyrzucę kilka myśli.

Zakładam, że aplikacja, którą chcesz przetestować jest następująca:

public static void Main()
{
    Console.WriteLine("Hello World");
}

Teraz, ponieważ nie mogę wymyślić żadnego dobrego sposobu testowania tego bezpośrednio, chciałbym rozbić zadanie pisania na interfejs.

public interface IOutputWriter
{
    void WriteLine(string line);
}

public class ConsoleWriter : IOutputWriter
{
    public void WriteLine(string line)
    {
        Console.WriteLine(line);
    }
}

I rozbij aplikację w ten sposób

public static void Main()
{
    IOutputWriter consoleOut = new ConsoleWriter();
    WriteHelloWorldToOutput(consoleOut);
}

public static void WriteHelloWorldToOutput(IOutputWriter output)
{
    output.WriteLine("Hello World");
}

Teraz masz punkt wtrysku do metody, która pozwala ci użyć wybranej przez siebie struktury do twierdzenia że metoda WriteLine jest wywoływana z parametrem "Hello World".

Problemy, które pozostawiłem nierozwiązane (i byłbym zainteresowany wejściem):

  1. Jak przetestować klasę ConsoleWriter, chyba nadal potrzebujesz jakiegoś frameworka testowego UI, aby to osiągnąć, a jeśli tak to cały problem w moot i tak...

  2. Testowanie głównej metody.

  3. Dlaczego mam wrażenie, że coś osiągnąłem zmieniając jedną linijkę nieprzetestowanego kodu na siedem linie kodu, z których tylko jedna jest faktycznie testowana (choć chyba zasięg ma poszedł w górę)

 3
Author: Martin Harris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 15:01:13

Zakładając, że znasz testowanie jednostkowe, a jednocześnie rozumiesz TDD "red green refactor process" (skoro powiedziałeś, że jesteś zaznajomiony z TDD) szybko wyjaśnij typowy proces myślowy tdd.

Twoje życie TDD będzie o wiele łatwiejsze, jeśli pomyślisz o konkretnej jednostce problemu i o każdej innej powiązanej Rzeczy należy myśleć w kategoriach zależności. oto przykład

Scenariusz:- Chcę, aby mój program wyświetlał hello world na konsoli.

TDD thought proces: -

"myślę, że mój program zacznie działać, a następnie wywoła program konsolowy, przekazując mu moją wiadomość i oczekuję, że mój program konsolowy wyświetli ją na ekranie"

"więc muszę przetestować, że kiedy uruchamiam mój program, powinien wywołać program konsoli"

"Jakie są zależności? hmm wiem, że program konsoli jest jednym z nich. Nie muszę się martwić, jak konsola dostanie wiadomość na ekran (wywołanie urządzenia io, drukowanie i takie tam) I muszę tylko wiedzieć, że mój program pomyślnie nazwał program konsoli. Muszę zaufać, że program konsoli działa, a jeśli nie, to w tej chwili nie jestem odpowiedzialny za testowanie i upewnianie się, że działa. odpowiedzialność, którą chcę przetestować, polega na tym, że mój program po uruchomieniu wywołuje program konsoli. "

"ale nawet nie wiem dokładnie, jaki program do konsoli wywołać. znam System.konsola.Writeline (konkretna realizacja), ale w przyszłości może się to zmienić ze względu na zmiana wymagań, więc co mam zrobić?"

"cóż, będę zależał od interfejsu (lub abstrakcji), a nie od konkretnej implementacji, wtedy będę mógł stworzyć fałszywą konsolę implementującą interfejs, z którym mogę przetestować"

  public interface Iconsole
    {
       void WriteToConsole(string msg);
    }



 public class FakeConsole : Iconsole
    {
        public bool IsCalled = false;

        public void WriteToConsole(string msg)
        {
            IsCalled = true;
        }
    }

Umieściłem iscalled member, którego "stan" zmieni się, jeśli kiedykolwiek program konsoli zostanie wywołany

OK wiem, że to brzmi jak długi proces myślenia, ale to się opłaca. TDD zmusza do myślenia przed kodowaniem, które jest lepsze niż kodowanie przed myślenie

Pod koniec dnia możesz wymyślić coś w rodzaju następującego sposobu wywołania programu:

var console = new FakeConsole();
    console.IsCalled = false;
    my_program program = new my_program(console);
    program.greet();

Przekazałem konsolę do my_program, więc my_program użyje konsoli do napisania naszej wiadomości na ekranie.

A mój my_program może wyglądać tak:

public class my_program
    {

        Iconsole _consol;
        public my_program(Iconsole consol)
        {
            if (consol != null)
                _consol = consol;
        }
        public void greet()
        {
            _consol.WriteToConsole("Hello world");
        }
    }

Ostateczny test jednostkowy będzie następujący:-

 [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");



        }
 3
Author: Samuel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-28 07:27:51

W Javie można przechwycić ("przekierować") System.out stream i przeczytać jego zawartość. Jestem pewien, że to samo można zrobić w C#. To tylko kilka linijek kodu w Javie, więc jestem pewien, że nie będzie to dużo więcej w C #

 2
Author: krosenvold,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 14:52:52

Naprawdę muszę się sprzeciwić temu pytaniu! Wszystkie metody mają swoje miejsce, a TDD jest dobre w wielu miejscach. Ale interfejsy użytkownika to pierwsze miejsce, w którym naprawdę wycofuję się z TDD. To, moim skromnym zdaniem, jest jednym z najlepszych uzasadnień wzorca projektowego MVC: przetestuj cholerstwo swoich Modeli i kontrolera programowo; wizualnie sprawdź swój widok. To o czym mówisz to kodowanie danych "Hello World" i testowanie, czy trafiają one na konsolę. Aby wykonać ten test w tym samym języku źródłowym, praktycznie musisz atrapy obiektu konsoli, który jest jedynym obiektem, który robi cokolwiek.

Alternatywnie, możesz napisać swój test w bash:

echo `java HelloWorldProgram`|grep -c "^Hello World$"
Trochę trudno dodać do zestawu testów JUnit, ale coś mi mówi, że to nigdy nie był plan....
 2
Author: David Berger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 15:19:37

Zgadzam się z Davidem Bergerem; oddziel interfejs i przetestuj model. Wygląda na to, że "model" w tym przypadku jest prostą klasą, która zwraca "Hello, world!". Test wyglądałby tak (w Javie):

  Greeter greeter = new Greeter();
  assertEquals("Hello World!", greeter.greet());

Stworzyłem zapis rozwiązania Hello World TDD style na http://ziroby.wordpress.com/2010/04/18/tdd_hello_world /.

 1
Author: Ron Romero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-08 23:09:23

Chyba coś takiego:

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);
    }
}
 0
Author: Jhonny D. Cano -Leftware-,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-27 14:48:58