GOOS一人読書会 第4回 AuctionSniperEndToEndTest.sniperJoinsAuctionUntilAuctionCloses() - 4

前回終了時点でのTODOリストは以下の通りです。


TODOリスト

商品ひとつ: 参加し、入札せずに落札に失敗する
 ApplicationRunnerを定義する

  AuctionSniperDriverを定義する
  Mainを定義し、自動でログインできるようにする

 FakeAuctionServerを定義する


  (仮実装)"スナイパーからの参加要求を受け取ったかどうか"の判定で空のメッセージでもOKとした
  (仮実装)"スナイパーへのオークション終了通知"が空のメッセージ

商品ひとつ: 参加し、入札し、落札に失敗する
商品ひとつ: 参加し、入札し、落札する
商品ひとつ: 価格の詳細を表示する
複数の商品を扱う
GUIから新しい商品を追加する
指値で入札をやめる

ということで、ようやく本体の実装を始めていきます。

package auctionsniper;

import javax.swing.SwingUtilities;

import auctionsniper.ui.MainWindow;

public class Main {
	public static final String MAIN_WINDOW_NAME = "Auction Sniper";
	public static final String STATUS_LOST = "Lost";
	public static final String STATUS_JOINING = "Joining";
	
	private MainWindow ui;
	
	public Main() throws Exception {
		startUserInterface();
	}
	
	public static void main(String ... args) throws Exception {
		Main main = new Main();
	}
	
	private void startUserInterface() throws Exception {
		SwingUtilities.invokeAndWait(new Runnable() {
			public void run() {
				ui = new MainWindow();
			}
		});
	}
}
package auctionsniper.ui;

import javax.swing.JFrame;

import auctionsniper.Main;

public class MainWindow extends JFrame {
	public MainWindow() {
		super("Auction Sniper");
		setName(Main.MAIN_WINDOW_NAME);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
}

本家githubリポジトリにならって、Mainクラスはauctionsniperパッケージに、MainWindowクラスはauctionsniper.uiパッケージに置きました。

こうしてパッケージを分離しておけば、本体で"test."から始まるパッケージをインポートしていたら明らかにおかしいってことが分かります。

invokeAndWait()がなにか、という事になりますが、これはSwingがシングルスレッド設計であり、ユーザインタフェースをイベントディスパッチ用のスレッド上に作らなければならないため、おまじないが必要ということみたいです。

これでようやくテストを実行できるようになりました。

テストを実行できるようになりましたが、当然失敗しますね。

エラーメッセージが本文102ページに載っています。

startBiddingIn()でshowsSniperStatus(STATUS_JOINING)を呼んでいるのですがスナイパーの状態を一切表示していないのでこのテストが失敗しています。

ということでスナイパーの状態を表示するラベルを追加します。

package auctionsniper.ui;

import javax.swing.JFrame;

import auctionsniper.Main;

public class MainWindow extends JFrame {
        public static final String SNIPER_STATUS_NAME = "sniper status";
        private final JLabel sniperStatus = createLabel(STATUS_JOINING);
	public MainWindow() {
		super("Auction Sniper");
		setName(Main.MAIN_WINDOW_NAME);
                add(sniperStatus);
                pack();
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
    
        private static JLabel createLabel(String initialText) {
                JLabel result = new JLabel(initialText);
                result.setName(SNIPER_STATUS_NAME);
                result.setBorder(new LineBorder(Color.BLACK));
                return result;
        }
}

これでJoiningの状態だけは表示出来るようになりましたが、今度は偽サーバがスナイパーから参加要求を受け取れないのでエラーになります。そんな処理を書いていないので当然ですね。

次回、そんな処理を書いていけたらいいですね♪