テスト駆動開発でストリームとコレクションを復習する
TextDocumentクラスと、テストケースのTextDocumentTestクラスを作成する。
ファイルを読み込む機能を用意する。
そのために、load()メソッドを作成する。
まずはテストを書く。
TextDocumentTest.java
import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import org.junit.Test; public class TextDocumentTest { @Test public void testLoad() { TextDocument td = new TextDocument(); boolean b = td.load("hoge.txt"); assertThat(b, is(true)); } }
コンパイルエラーを解消するために、TextDocumentクラスにload()メソッドを追加する。
TextDocument.java
public class TextDocument { public boolean load(String path) { return false; } }
テストを実行するとエラーになるので、load()メソッドの戻り値をtrueに変更する。(Fake)
TextDocument.java
public class TextDocument { public boolean load(String path) { return true; } }
テストにパスするのでめでたしめでたし。
テストケースに、パスしないテストを追加する。
TextDocumentTest.java
import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import org.junit.Test; public class TextDocumentTest { @Test public void testLoadNG() { TextDocument td = new TextDocument(); boolean b = td.load("aaa.txt"); assertThat(b, is(false)); } @Test public void testLoad() { TextDocument td = new TextDocument(); boolean b = td.load("hoge.txt"); assertThat(b, is(true)); } }
このテストをパスするようにするには、まじめに実装しないといけない。
TextDocument.java
import java.io.File; public class TextDocument { public boolean load(String path) { File f = new File(path); if (!f.exists()) return false; return true; } }
次に、ファイルの行数を取得するメソッドを作ることにする。
hoge.txt は11行なので、テストコードは以下のようになる。
TextDocumentTest.java
@Test public void testLines() { TextDocument td = new TextDocument(); boolean b = td.load("hoge.txt"); assertThat(b, is(true)); int lines = td.getLines(); assertThat(lines, is(11)); }
このテストをパスするには、Fakeすればよい。
TextDocument.java
import java.io.File; public class TextDocument { public boolean load(String path) { File f = new File(path); if (!f.exists()) return false; return true; } public int getLines() { return 11; } }
Fakeコードではテストにパスしないようにするために、1行だけのファイル 1.txt を用意し、そのファイルの行数を検査するテストを追加する。
TextDocumentTest.java
@Test public void testLines() { TextDocument td = new TextDocument(); boolean b = td.load("hoge.txt"); assertThat(b, is(true)); int lines = td.getLines(); assertThat(lines, is(11)); } @Test public void testLines1() { TextDocument td = new TextDocument(); boolean b = td.load("1.txt"); assertThat(b, is(true)); int lines = td.getLines(); assertThat(lines, is(1)); }
このテストをパスするために、TextDocumentクラスをきちんと実装する。
java.util.List を使用してコレクションフレームワークの復習をする。
List の要素として、ファイルの各行を追加する。
TextDocument.java
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class TextDocument { private List<String> lines; public boolean load(String path) { lines = new ArrayList<String>(); File f = new File(path); if (!f.exists()) return false; try (BufferedReader in = new BufferedReader(new FileReader(path))) { while (in.ready()) { String s = in.readLine(); lines.add(s); } } catch (IOException e) { e.printStackTrace(); } return true; } public int getLines() { return lines.size(); } }
ファイル読み込みができた人は、以下の機能を追加しましょう!
- 指定した行の文字列取得
- 指定した行を削除(削除した行の文字列を返す)
- 指定した文字列を行として末尾に挿入
- 指定した場所に指定した文字列を行として挿入
- 出力先ファイル名を指定してファイル出力
上記機能追加ができたら、さらに以下の機能を追加しましょう!
- 文字列検索(行番号と、その行の文字列を、Listで返す)
- 文字列置換(検索と同じように返す)
指定した行の文字列を取得
まずはテストを書く。
TextDocumentTest.java
@Test public void testGetLine() { TextDocument td = new TextDocument(); boolean b = td.load("hoge.txt"); String s = td.getLine(0); assertThat(s, is("ab")); }
TextDocumentにはgetLine()メソッドがないので、Eclipseに作ってもらう。
TextDocument.java
public String getLine(int i) { return null; }
テストを実行するとエラーになるので、テストをパスするように “ab”を返すようにFakeする。
TextDocument.java
public String getLine(int i) { return "ab"; }
テストを追加する。
TextDocumentTest.java
@Test public void testGetLine() { TextDocument td = new TextDocument(); boolean b = td.load("hoge.txt"); String s = td.getLine(0); assertThat(s, is("ab")); s = td.getLine(1); assertThat(s, is("abc")); }
テストを実行するとエラーになるので、テストにパスするようにコードを修正する。
TextDocument.java
public String getLine(int i) { return lines.get(i); }
指定した行を削除
まずはテストを書く。
削除した行の文字列を返す。
TextDocumentTest.java
@Test public void testDelete() { TextDocument td = new TextDocument(); td.load("hoge.txt"); String s = td.deleteLine(0); assertThat(s, is("ab")); }
EclipseにdeleteLine()メソッドを作ってもらう。
TextDocument.java
public String deleteLine(int i) { return null; }
テストを実行してもパスしないので、”ab”を返すようにFakeする。
TextDocument.java
public String deleteLine(int i) { return "ab"; }
テストを追加する。
1行目を削除したら、もともと2行目だったものが1行目になるはず。
TextDocumentTest.java
@Test public void testDelete() { TextDocument td = new TextDocument(); td.load("hoge.txt"); String s = td.deleteLine(0); assertThat(s, is("ab")); s = td.getLine(0); assertThat(s, is("abc")); }
TextDocumentのdeleteLine()を修正。
TextDocument.java
public String deleteLine(int i) { return lines.remove(i); }
指定した文字列を行として末尾に挿入
まずはテストを書く。
1行追加すれば、行数が増えるはず。
TextDocumentTest.java
@Test public void testAdd() { TextDocument td = new TextDocument(); td.load("hoge.txt"); int lines = td.getLines(); assertThat(lines, is(10)); td.addLine("1234567890"); lines = td.getLines(); assertThat(lines, is(11)); }
EclipseにaddLine()を作ってもらう。
テストするとエラーになるので、テストにパスする実装を追加する。
TextDocument.java
public void addLine(String s) { lines.add(s); }
指定した場所に指定した文字列を行として挿入
まずはテストを書く。
どこに追加するのかを引数で渡す。
先頭に1行追加すれば、行数が増えるはず。
先頭行は追加した文字列に一致するはず。
2行目は、もともと1行目だった文字列に一致するはず。
TextDocumentTest.java
@Test public void testAdd1() { TextDocument td = new TextDocument(); td.load("hoge.txt"); int lines = td.getLines(); assertThat(lines, is(10)); td.addLine(0, "1234567890"); lines = td.getLines(); assertThat(lines, is(11)); String s = td.getLine(0); assertThat(s, is("1234567890")); s = td.getLine(1); assertThat(s, is("ab")); }