5月10日

コレクションフレームワークの練習として、音楽プレーヤーみたいなアプリを作ってみる。

アプリを作成するために、新規Javaプロジェクトとして「musicplayer」プロジェクトを作成する。

新規クラスで「MusicPlayer」を作成する。
このとき、パッケージ名は「jp.abc」とする。
一般的にパッケージ名を決める場合は、企業やアプリのドメイン名を反転したものを使用する。
そうしておけば、世界的に重複する心配がないので。

例:
twitter.com → com.twitter.Hoge
gmail.google.com → com.google.gmail

package jp.abc;

public class MusicPlayer {

}

テストクラスを作成する。
[新規]-[その他] から「JUnitテストケース」を選択する。

package jp.abc;

import org.junit.jupiter.api.Test;

class MusicPlayerTest {

	@Test
	void 音楽を追加する() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
	}

}

addMusic()上にマウスカーソルをもっていき、「addMusic(String, String)を作成する」をクリックすると、
MusicPlayerにメソッドが追加される。
引数名が不適切なので、修正する。

package jp.abc;

public class MusicPlayer {

	public void addMusic(String title, String artist) {

	}

}

音楽を追加した後の動作を考える。
とりあえず、音楽の数を調べたいので、テストケースにメソッドを追加する。

package jp.abc;

import org.junit.jupiter.api.Test;

class MusicPlayerTest {

	@Test
	void 音楽を追加する() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		int n = mp.countMusic();
	}

}

countMusic()がコンパイルエラーなので、マウスカーソルをその上に移動し、「countMusic()を作成する」をクリックし、メソッドを作成する。

package jp.abc;

public class MusicPlayer {

	public void addMusic(String title, String artist) {

	}

	public int countMusic() {
		return 0;
	}

}

テストを追加する。

package jp.abc;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class MusicPlayerTest {

	@Test
	void 音楽を追加する() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		int n = mp.countMusic();
		assertThat(n, is(1));
		mp.addMusic("flamingo", "米津玄師");
		n = mp.countMusic();
		assertThat(n, is(2));
	}

}

テストを実行するとエラーになるので、MusicPlayerをそれなりに実装する必要性が発生する。

package jp.abc;

import java.util.ArrayList;
import java.util.List;

public class MusicPlayer {
	private List<Music> musics = new ArrayList<>();

	public void addMusic(String title, String artist) {
		Music m = new Music();
		musics.add(m);
	}

	public int countMusic() {
		return musics.size();
	}

}

テストをパスできたので、新しい機能を追加する。
そのために、テストを追加する。

package jp.abc;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class MusicPlayerTest {

	@Test
	void 音楽を追加する() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		int n = mp.countMusic();
		assertThat(n, is(1));
		mp.addMusic("flamingo", "米津玄師");
		n = mp.countMusic();
		assertThat(n, is(2));
	}

	@Test
	void タイトルとアーティストの確認() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		Music m = mp.getMusic(0);
	}
}

getMusic()でコンパイルエラーになっているので、マウスカーソルを上に持っていき「getMusic()を作成する」をクリックし、メソッドを作成する。

package jp.abc;

import java.util.ArrayList;
import java.util.List;

public class MusicPlayer {
	private List<Music> musics = new ArrayList<>();

	public void addMusic(String title, String artist) {
		Music m = new Music();
		musics.add(m);
	}

	public int countMusic() {
		return musics.size();
	}

	public Music getMusic(int i) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

}

テストを追加する。

package jp.abc;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class MusicPlayerTest {

	@Test
	void 音楽を追加する() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		int n = mp.countMusic();
		assertThat(n, is(1));
		mp.addMusic("flamingo", "米津玄師");
		n = mp.countMusic();
		assertThat(n, is(2));
	}

	@Test
	void タイトルとアーティストの確認() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		Music m = mp.getMusic(0);
		assertNotNull(m);
	}
}

テストがエラーになるので、テストにパスするようにMusicPlayerを変更する。

package jp.abc;

import java.util.ArrayList;
import java.util.List;

public class MusicPlayer {
	private List<Music> musics = new ArrayList<>();

	public void addMusic(String title, String artist) {
		Music m = new Music();
		musics.add(m);
	}

	public int countMusic() {
		return musics.size();
	}

	public Music getMusic(int i) {
		return new Music();
	}

}

テストを追加する。

package jp.abc;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class MusicPlayerTest {

	@Test
	void 音楽を追加する() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		int n = mp.countMusic();
		assertThat(n, is(1));
		mp.addMusic("flamingo", "米津玄師");
		n = mp.countMusic();
		assertThat(n, is(2));
	}

	@Test
	void タイトルとアーティストの確認() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		Music m = mp.getMusic(0);
		assertNotNull(m);
		assertThat(m.getTitle(), is("Lemon"));
	}
}

getTitle()のコンパイルエラーを解消する。

package jp.abc;

public class Music {

	public String getTitle() {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

}

コンパイルエラーが解消したけどテストはエラーなので、テストにパスするように、戻り値で”Lemon”を返す。

package jp.abc;

public class Music {

	public String getTitle() {
		return "Lemon";
	}

}

さらにテストを追加する。

package jp.abc;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class MusicPlayerTest {

	@Test
	void 音楽を追加する() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		int n = mp.countMusic();
		assertThat(n, is(1));
		mp.addMusic("flamingo", "米津玄師");
		n = mp.countMusic();
		assertThat(n, is(2));
	}

	@Test
	void タイトルとアーティストの確認() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		Music m = mp.getMusic(0);
		assertNotNull(m);
		assertThat(m.getTitle(), is("Lemon"));
		mp.addMusic("flamingo", "米津玄師");
		m = mp.getMusic(1);
		assertNotNull(m);
		assertThat(m.getTitle(), is("flamingo"));
	}
}

きちんと実装しないとテストにパスしないっぽい。。。
Musicクラスにタイトルとアーティストを保存できるよう、最小限の実装をする。

package jp.abc;

public class Music {
	private String title;
	private String artist;

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getArtist() {
		return artist;
	}

	public void setArtist(String artist) {
		this.artist = artist;
	}

}

MusicPlayerも、addMusic()とgetMusoic()をきちんと実装する。

package jp.abc;

import java.util.ArrayList;
import java.util.List;

public class MusicPlayer {
	private List<Music> musics = new ArrayList<>();

	public void addMusic(String title, String artist) {
		Music m = new Music();
		m.setTitle(title);
		m.setArtist(artist);
		musics.add(m);
	}

	public int countMusic() {
		return musics.size();
	}

	public Music getMusic(int i) {
		return musics.get(i);
	}

}

これでテストにパスできるようになった!

音楽プレーヤーにプレイリストを追加できるようにする。
テストを追加する。

package jp.abc;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class MusicPlayerTest {

	@Test
	void 音楽を追加する() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		int n = mp.countMusic();
		assertThat(n, is(1));
		mp.addMusic("flamingo", "米津玄師");
		n = mp.countMusic();
		assertThat(n, is(2));
	}

	@Test
	void タイトルとアーティストの確認() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		Music m = mp.getMusic(0);
		assertNotNull(m);
		assertThat(m.getTitle(), is("Lemon"));
		mp.addMusic("flamingo", "米津玄師");
		m = mp.getMusic(1);
		assertNotNull(m);
		assertThat(m.getTitle(), is("flamingo"));
	}
	
	@Test
	void プレイリストを作る() {
		MusicPlayer mp = new MusicPlayer();
		mp.addPlayList("お気に入り");
	}
}

MusicPlayerにaddPlayList()を追加してコンパイルエラーを解消する。

package jp.abc;

import java.util.ArrayList;
import java.util.List;

public class MusicPlayer {
	private List<Music> musics = new ArrayList<>();

	public void addMusic(String title, String artist) {
		Music m = new Music();
		m.setTitle(title);
		m.setArtist(artist);
		musics.add(m);
	}

	public int countMusic() {
		return musics.size();
	}

	public Music getMusic(int i) {
		return musics.get(i);
	}

	public void addPlayList(String name) {

	}

}

テストを追加する。
Musicと同様に、プレイリストの数を返す機能を追加してみる。

	@Test
	void プレイリストを作る() {
		MusicPlayer mp = new MusicPlayer();
		mp.addPlayList("お気に入り");
		int n = mp.countPlayList();
		assertThat(n, is(1));
	}

countPlayList()を作成してコンパイルエラーを解消する。
「return 1;」でテストにパスする。

	public int countPlayList() {
		return 1;
	}

さらにプレイリストを追加する。
テストがエラーになるので、パスするようにMusicPlayerを実装する。

	@Test
	void プレイリストを作る() {
		MusicPlayer mp = new MusicPlayer();
		mp.addPlayList("お気に入り");
		int n = mp.countPlayList();
		assertThat(n, is(1));
		mp.addPlayList("バラード集");
		n = mp.countPlayList();
		assertThat(n, is(2));
	}

addMusic()とcountMusic()を参考にして実装する。

package jp.abc;

import java.util.ArrayList;
import java.util.List;

public class MusicPlayer {
	private List<Music> musics = new ArrayList<>();
	private List<PlayList> playLists = new ArrayList<>();

	public void addMusic(String title, String artist) {
		Music m = new Music();
		m.setTitle(title);
		m.setArtist(artist);
		musics.add(m);
	}

	public int countMusic() {
		return musics.size();
	}

	public Music getMusic(int i) {
		return musics.get(i);
	}

	public void addPlayList(String name) {
		playLists.add(new PlayList());
	}

	public int countPlayList() {
		return playLists.size();
	}

}

プレイリストを取得するテストを追加する。

	@Test
	void プレイリスト名を調べる() {
		MusicPlayer mp = new MusicPlayer();
		mp.addPlayList("お気に入り");
		PlayList p = mp.getPlayList(0);
		assertNotNull(p);
	}

getPlayList()のコンパイルエラーを解消する。
MusicPlayerにメソッドを追加する。

	public PlayList getPlayList(int i) {
		return null;
	}

テストがエラーになるので、fakeでテストにパスさせる。

	public PlayList getPlayList(int i) {
		return new PlayList();
	}

テストを追加する。

	@Test
	void プレイリスト名を調べる() {
		MusicPlayer mp = new MusicPlayer();
		mp.addPlayList("お気に入り");
		PlayList p = mp.getPlayList(0);
		assertNotNull(p);
		String s = p.getName();
		assertThat(s, is("お気に入り"));
	}

getName() のコンパイルエラーを解消する。

package jp.abc;

public class PlayList {

	public String getName() {
		return null;
	}

}

テストがエラーになるので、fakeでテストにパスさせる。

package jp.abc;

public class PlayList {

	public String getName() {
		return "お気に入り";
	}

}

テストを追加する。

	@Test
	void プレイリスト名を調べる() {
		MusicPlayer mp = new MusicPlayer();
		mp.addPlayList("お気に入り");
		PlayList p = mp.getPlayList(0);
		assertNotNull(p);
		String s = p.getName();
		assertThat(s, is("お気に入り"));
		mp.addPlayList("バラード集");
		p = mp.getPlayList(1);
		assertThat(p.getName(), is("バラード集"));
	}

テストにパスするようにMusicPlayerを実装する。

package jp.abc;

import java.util.ArrayList;
import java.util.List;

public class MusicPlayer {
	private List<Music> musics = new ArrayList<>();
	private List<PlayList> playLists = new ArrayList<>();

	public void addMusic(String title, String artist) {
		Music m = new Music();
		m.setTitle(title);
		m.setArtist(artist);
		musics.add(m);
	}

	public int countMusic() {
		return musics.size();
	}

	public Music getMusic(int i) {
		return musics.get(i);
	}

	public void addPlayList(String name) {
		PlayList p = new PlayList();
		p.setName(name);
		playLists.add(p);
	}

	public int countPlayList() {
		return playLists.size();
	}

	public PlayList getPlayList(int i) {
		return playLists.get(i);
	}

}

プレイリストに音楽を追加できるようにしたい!
テストを追加する。

	@Test
	void プレイリストに音楽を追加する() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		mp.addPlayList("お気に入り");
		Music m = mp.getMusic(0);
		assertThat(m.getTitle(), is("Lemon"));
		PlayList p = mp.getPlayList(0);
		mp.addMusicToPlayList(m, p);
		int n = p.countMusic();
		assertThat(n, is(1));
	}

コンパイルエラーを解消する。

package jp.abc;

public class PlayList {
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int countMusic() {
		return 0;
	}

}

fakeでテストにパスさせる。

package jp.abc;

public class PlayList {
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int countMusic() {
		return 1;
	}

}

テストを追加する。

	@Test
	void プレイリストに音楽を追加する() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusic("Lemon", "米津玄師");
		mp.addMusic("flamingo", "米津玄師");
		mp.addPlayList("お気に入り");
		Music m = mp.getMusic(0);
		assertThat(m.getTitle(), is("Lemon"));
		PlayList p = mp.getPlayList(0);
		mp.addMusicToPlayList(m, p);
		int n = p.countMusic();
		assertThat(n, is(1));
		m = mp.getMusic(1);
		mp.addMusicToPlayList(m, p);
		n = p.countMusic();
		assertThat(n, is(2));
	}

TDDするときは、エラー状態でその日の作業を終える。
次に作業を再開するとき、テストを実行すればエラーが出るので、そこから再開すればいいことがすぐにわかる。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください