= 拡張Wicketテスタ = ここでは、Wicketに標準で備わっている[[wicket/Problems|ひどいテスタ]]の代わりに、タイプセーフでリファクタリングに強い代替のテスタを提案してみる。 == ひどいWicketプログラムとそのテスト == ひどいとは言っても、ごく普通に書くとこうなる。 {{{ Login
メールアドレス
パスワード
}}} {{{ import org.apache.wicket.markup.html.*; import org.apache.wicket.markup.html.form.*; import org.apache.wicket.markup.html.panel.*; import org.apache.wicket.model.*; public class LoginPage extends WebPage { public LoginPage() { add(new FeedbackPanel("feedback")); add(new LoginForm()); } class LoginForm extends Form { private LoginForm() { super("loginForm"); add(new TextField("email", new Model())); add(new PasswordTextField("pass", new Model())); } @Override public void onSubmit() { String mail = get("email").getDefaultModelObjectAsString(); String pass = get("pass").getDefaultModelObjectAsString(); // login success or failed .... } } } }}} {{{ import org.apache.wicket.util.tester.*; import org.junit.*; public class LoginTest { @Test public void test() { WicketTester tester = new WicketTester(); tester.startPage(LoginPage.class); tester.assertRenderedPage(LoginPage.class); tester.assertNoErrorMessage(); FormTester formTester = tester.newFormTester("loginForm"); formTester.setValue("email", "sysdba"); formTester.setValue("pass", "masterkey"); formTester.submit(); tester.assertNoErrorMessage(); } } }}} == LoginPageの改良 == 少なくともLoginPageクラスは以下のようにし、文字列ではなく文字列定数を参照すべきだろう。 {{{ import org.apache.wicket.markup.html.*; import org.apache.wicket.markup.html.form.*; import org.apache.wicket.markup.html.panel.*; import org.apache.wicket.model.*; public class LoginPage extends WebPage { static final String ID_FEEDBACK = "feedback"; static final String ID_LOGINFORM = "loginForm"; static final String ID_EMAIL = "email"; static final String ID_PASS = "pass"; public LoginPage() { add(new FeedbackPanel(ID_FEEDBACK)); add(new LoginForm()); } class LoginForm extends Form { private LoginForm() { super(ID_LOGINFORM); add(new TextField(ID_EMAIL, new Model())); add(new PasswordTextField(ID_PASS, new Model())); } @Override public void onSubmit() { String mail = get(ID_EMAIL).getDefaultModelObjectAsString(); String pass = get(ID_PASS).getDefaultModelObjectAsString(); // login success or failed .... } } } }}} さらにLoginPageTestも以下のように、その文字列定数を参照させる。 {{{ import org.apache.wicket.util.tester.*; import org.junit.*; import static test.LoginPage.*; public class LoginTest { @Test public void test() { WicketTester tester = new WicketTester(); tester.startPage(LoginPage.class); tester.assertRenderedPage(LoginPage.class); tester.assertNoErrorMessage(); FormTester formTester = tester.newFormTester(ID_LOGINFORM); formTester.setValue(ID_EMAIL, "sysdba"); formTester.setValue(ID_PASS, "masterkey"); formTester.submit(); tester.assertNoErrorMessage(); } } }}} == 本当はこのようにしたい == LoginPage側では、テストで参照されるであろうコンポーネントをフィールドとして保持しておく。 これは問題ない。 {{{ import org.apache.wicket.markup.html.*; import org.apache.wicket.markup.html.form.*; import org.apache.wicket.markup.html.panel.*; import org.apache.wicket.model.*; public class LoginPage extends WebPage { static final String ID_FEEDBACK = "feedback"; static final String ID_LOGINFORM = "loginForm"; static final String ID_EMAIL = "email"; static final String ID_PASS = "pass"; LoginForm loginForm; public LoginPage() { add(new FeedbackPanel(ID_FEEDBACK)); add(loginForm = new LoginForm()); } class LoginForm extends Form { TextFieldemailField; PasswordTextField passField; private LoginForm() { super(ID_LOGINFORM); add(emailField = new TextField(ID_EMAIL, new Model())); add(passField = new PasswordTextField(ID_PASS, new Model())); } @Override public void onSubmit() { String mail = emailField.getDefaultModelObjectAsString(); String pass = passField.getDefaultModelObjectAsString(); // login success or failed .... } } } }}} テストの方は以下のようにしたい。ID文字列は一切使わず、コンポーネントのみを参照する。 これはWicket付属のテスターではできない。 {{{ public class LoginTest { @Test public void test() { WicketTester tester = new WicketTester(); tester.startPage(LoginPage.class); tester.assertRenderedPage(LoginPage.class); tester.assertNoErrorMessage(); LoginPage loginPage = tester.getLastRenderedPage(); LoginForm loginForm = loginPage.loginForm; FormTester formTester = tester.newFormTester(loginForm); formTester.setValue(loginForm.emailField, "sysdba"); formTester.setValue(loginForm.passField, "masterkey"); formTester.submit(); tester.assertNoErrorMessage(); } } }}} == 拡張Wicketテスタ == ということで、[[wicket/ExWicketTester/Source|ソースはこちら]]。 これを使うとテストユニットは次のように書ける。 {{{ import org.junit.*; import test.LoginPage.*; import com.cm55.third.wicket.test.*; public class LoginTest { @Test public void test() { ExWicketTester tester = new ExWicketTester(); LoginPage loginPage = tester.startPage(LoginPage.class); tester.assertRenderedPage(LoginPage.class); tester.assertNoErrorMessage(); LoginForm loginForm = loginPage.loginForm; ExFormTester formTester = tester.newFormTester(loginForm); formTester.setValue(loginForm.emailField, "sysdba"); formTester.setValue(loginForm.passField, "masterkey"); formTester.submit(); tester.assertNoErrorMessage(); } } }}}