2015/01/17

JDepends

はじめに.

Javaパッケージ単位でメトリクス計測するにはJDependが使える.
JDependは次のメトリクスを計測する.

  • 抽象クラスの数(AC: Abstract Classes)
  • 具象クラスの数(CC: Concrete Classes)
  • 1パッケージに依存する他パッケージの数(Ca: Afferent Couplings)
  • パッケージが依存する他パッケージの数(Ce: Efferent Couplings)
  • 抽象度合(A: Abstractness )
  • 不安定性(I: Instability)
  • 距離(D: Distance)

Afferent Couplings

Ca値. この値が大きいほど当該パッケージが他パッケージから参照されている.
Ca値の高いパッケージに対する変更は他パッケージへの変更波及性が高くなる傾向にある.

Efferent Couplings

Ce値. この値が大きいほど当該パッケージが他パッケージを参照している.
Ce値の高いパッケージは他パッケージの変更による影響を受けやすい傾向にある.

Abstractness

A値. 当該パッケージが内包する抽象クラスorインタフェースの度合い.
A = AC / (AC + CC)で求められる.
A値の高いパッケージは外部への変更波及性が小さくなる傾向にある.
もう1つの観点として, 当該パッケージのCa値が低い場合, 抽象度を高くする必要性は低いと言える.

Instability

I値. 当該パッケージの不安定度合い. 当該パッケージが変更を必要とされる頻度である.
I = Ce / (Ce + Ca)で求められる.
I値が大きい程, 他パッケージに依存しており, I値が低い程, 他パッケージから依存されていることを
意味する.
この値が大きい程, 外部の変更による影響を受けやすく, 当該パッケージも変更が必要となりやすい傾向にある.
この値が小さい程, 外部に与える影響が高いため当該パッケージの変更には注意する必要がある.

Distance

D値. 当該パッケージが他パッケージとどの程度隔離されているかの度合い.
D = abs((A + I) - 1)で求められる.
メトリクス計測ではこのD値が重要な指標となる.

いくつかのメトリクスを見てみる.

A = 0, I = 1, Ce = 8, Ca = 0
パッケージの抽象可はされていないものの, Caが0であるため変更波及性は低く, このパッケージは変更しやすい.
D値は0となり, パッケージの状態は良好といえる.

A = 0.4, I = 0.6, Ce = 3, Ca = 2
不安定性がやや高いものの, 抽象度合いも確保されているため, 外部に与える影響は少なく済む.
D値は0となり, パッケージの状態は良好といえる.

A = 0, I = 0.2, Ce = 1, Ca = 4
全く抽象化されていないパッケージ. Ca値が高く外部からの依存度合いも高い.
そのため, 当該パッケージを変更することによる変更波及性は高くなってしまう.
D値は0.8となり, パッケージの状態は悪いといえる.

A = 0.6, I = 1
当該パッケージは外部から依存されていないにも関わらず抽象度合が高いことを示す.
D値は0.6となり, パッケージの状態は改善の余地があるといえる.

一般的に, 依存されている度合い(Ca値)の高いパッケージは抽象度を高くする方が好まれる(.結果, D値が低くなる)

Gradle

apply plugin: 'jdepend'

task(jdepend, type: JDepend) {
    classesDir = file('build/intermediates/classes/debug/')
    reports {
        xml.enabled false
        text.enabled true
    }
}

参考

JDependsExtension

Android:Robotium

はじめに.

RobotiumはAndroidのブラックボックステストを自動化するUIテストフレームワーク.
シナリオを手軽にかけて導入も非常に簡単である. 老舗のテストフレームワークでもあり動作は安定している.

本稿はRobotiumを導入したレポートである.

確認環境は次の通り.

  • Robotium: 5.2.1
  • Android Studio 1.0
  • Mac 10.9.5

環境準備

環境準備は次のコードをgradleに追加するのみで完了.

dependencies {
    ...
    androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.2.1'
}

簡単. あとはテストコードを書いていく.

サンプルコード

RobotiumではメインとなるSoloクラスをsetUpで初期化する.
下記のコードはテスト開始時にMainActivityを起動し, テスト終了時にfinishさせる簡易なものである.

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
    private Solo solo = null;

    public MainActivityTest() {
        super(MainActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        solo = new Solo(getInstrumentation(), getActivity());
        super.setUp();
    }

    @Override
    protected void tearDown() throws Exception {
        solo.finishOpenedActivities();
        super.tearDown();
    }

    public void testMainActivity() {
        // ここにシナリオを記述する
    }
}

TestCaseのそれと同じく, testメソッドにシナリオを書いていく.
下記は次の手順をシナリオ化したもの.

  1. MainActivityが起動できているかを検査
  2. id.buttonをクリック
  3. ダイアログオープンをウェイト
  4. ダイアログに表示されているテキストを検査
  5. “Yes”を押下
  6. 表示されるToastに表示されている
    public void testMainActivity() {
        solo.assertCurrentActivity("wrong activity", MainActivity.class);
        solo.waitForActivity(MainActivity.class);
        solo.clickOnView(solo.getCurrentActivity().findViewById(R.id.button));
        solo.waitForDialogToOpen();
        Assert.assertTrue("wrong dialog text", solo.searchText("Test"));
        solo.clickOnButton("Yes");
        Assert.assertTrue("wrong toast text", solo.searchText("Hello!"));
    }

RobotiumはInstrumentationTestCaseがベースであるため, Android Testing Frameworkのそれと同じように扱える.
普段通りAndroidTestとして実行すればRobotiumのテストが実行できる.

以上.