新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。もう新人じゃないかも…

Javaの学習:実用的なリフレクション(3)

[Java] Javaの学習

内容:9章 実用的なリフレクション

JUnit
  • 単体テストの自動化を行うためのフレームワーク
  • 機能を追加した場合に回帰テストを楽に実行できる
  • 使い方(JUnit3.0)
    • 「新規」>「JUnitテスト・ケース」でTestXxxxクラスを作成(TestCaseクラスが拡張される)
    • @Testアノテーションを付けたtestXxxxメソッドを作成
      • fail()を入れて失敗する(testXxxメソッドが呼ばれている)ことを確認
      • その後テストしたい内容を書く、基本はassertEquals(期待する結果, クラスのメソッド)
      • 例外の発生チェックの場合、try { クラスのメソッド(); fail(); } catch { } (catchされなければfail)
      • 各テストメソッドの実行前に必ず実行される初期化設定はsetUp()を、終了時処理はtearDown()をオーバライドする
import static org.junit.Assert.*;

import org.junit.Test;

public class MathTest {
	void setUp() {
		/* 初期化処理 */
	}
	
	@Test
	public void testAdd() {
		assertEquals(5, Math.addExact(2, 3));
	}
	
	@Test
	public void testAbs() {
		assertEquals(5, Math.abs(-5));
	}
}  
リフレクション+Junit=安定コード
  • コードをどこまでテストすべきか?
    • 理想としては、製品のすべてをテストすべき
    • 期日などの制限から不可能、コードを書くよりテストケースを作るのにより多くの時間を取られがち
    • リフレクションを使えば、どのようなプロパティを宣言しても、データモデルオブジェクトをテストできる
public class TestMutableObject extends TestCase {
    private Class type = null;

    protected TestMutableObject(final Class type, final String testName) {
        super(testName);
        assert (type != null);
        assert (MutableObject.class.isAssignableFrom(type));
        this.type = type;
    }

    public static Test suite(final Class type) {
        if (type == null) { trow new NullPointerException("type"); }
        if (!MutableObject.class.isAssignableFrom(type) ) { throw new IllegalArgumentException("type"); }
        
        TestSuite suite = new TestSuite(type.getName());
        suite.addTest(new TestMutableObject(type, "testConstraintsExists"));
        return suite;
    }

    public void testConstraintsExist() {
        try {
            final PropertyDesctiptor[] props = 
                Introspector.getBeanInfo(type, Object.class).getPropertyDescriptors();
            
            for (PropertyDescriptor pd : props) {
                ObjectConstraint const = MutableObject.getConstraint(type, pd.getName());
                assertNotNull("プロパティ" + pd.getName() + "には制約がありません。", constraint);
            }
        } catch (final IntrospectionException e) {
            throw new RuntimeException():
        }
    }
}

// テスト実行用
public class BankDataTests {
    public static Test suite() {
        TestSuite suite = new TestSuite("データモデルのテスト");
        suite.addTest(TestMutableObject.suite(Customer.class));
        suite.addTest(TestMutableObject.suite(Employee.class));
        suite.addTest(TestMutableObject.suite(Person.class));
        ...
        return suite;
    }

    public static void main(final String[] args) {
        TestRunner.run(BankDataTests.class);
    }
}