Exercise 2

Es soll ein Eingabewort eingelesen und anschließend mit seiner Zeichenanzahl ausgegeben werden.
Als Vorbedingungen soll man sichergehen, dass

  • Der Ausgabestring das eingegebene Wort enthält.
  • Es soll ein einzelnes Konstrukt für die Ausgabe verwendet werden, also keine Konkatenationen oder dergleichen.
  • Um die Länge des Eingabeworts zu ermitteln, sollen in der Sprache eingebaute Funktionen verwendet werden und nicht etwa eine For-Schleife zum Zählen.

Mein Test hierfür sieht wie folgt aus:

package de.mike.kata.exercices;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintStream;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

@RunWith(JUnitPlatform.class)
class Exercise2Test {

	private InputStream stdin;
	private ByteArrayOutputStream stdout;

	@BeforeEach
	void prepareStdIn() {
		stdin = System.in;
		stdout = new ByteArrayOutputStream();
		System.setOut(new PrintStream(stdout));
	}

	@Test
	@DisplayName("A single string without whitespaces.")
	void testSimpleString() throws Exception {
		System.setIn(new ByteArrayInputStream("single_word".getBytes()));
		Exercise2.main(null);

		assertThat(stdout.toString(), is("What is the input string?\nsingle_word has 11 characters."));
	}

	@Test
	@DisplayName("A complex string with outer and inner whitespaces.")
	void testComplexStrings() throws Exception {
		System.setIn(new ByteArrayInputStream("\tmultiple words for input ".getBytes()));
		Exercise2.main(null);
		
		assertThat(stdout.toString(), is("What is the input string?\n\tmultiple words for input  has 24 characters."));
	}
	
	@Test
	@DisplayName("A string with only whitespaces should not be possible.")
	void testEmptyString() throws Exception {
		System.setIn(new ByteArrayInputStream("  \n".getBytes()));
		System.setIn(new ByteArrayInputStream("\t\n".getBytes()));
		System.setIn(new ByteArrayInputStream("\n".getBytes()));
		System.setIn(new ByteArrayInputStream("word".getBytes()));
		Exercise2.main(null);
		
		assertThat(stdout.toString(), is("What is the input string?\nword has 4 characters."));
	}
	
	@AfterEach
	void resetStdIn() {
		System.setIn(stdin);
	}
}

Die dazugehörige Implementierung ist (beispielsweise) folgende:

package de.mike.kata.exercices;

import java.io.IOException;
import java.util.Scanner;

public class Exercise2 {
	
	public static void main(String[] args) throws IOException {
		System.out.printf("What is the input string?\n");
		String input = null;
		Scanner scanner = new Scanner(System.in);
		do {
			input = scanner.nextLine();
		} while (input == null);
		System.out.printf("%s has %d characters.", input, input.trim().length());
		scanner.close();
	}

}

Die Besonderheit aus meiner Sicht bzw. meine persönliche Schwierigkeit dabei war es, im Test zu simulieren, dass ich eine Falscheingabe mache und dann eine while-Schleife in der Implementierung erzwinge, um sicherzugehen, dass der Inputstring vorher eingelesen wird.