月別アーカイブ: 2010年5月

Subversionのインストール (CentOS 5.5 64bit)

CVS、Subversion、VSS等、世の中にはバージョン管理ソフト (システム?) と呼ばれるソフトが数多くあります。プログラムソースの変更履歴を容易に管理可能なため、一度使うと手放せなくなってしまいます。

通常は既に準備されている環境を使用することが多いため自分自身で立ち上げる機会は少ないですが、せっかくですので centos_x86_64 (CentOS 5.5 64bit環境) に Subversion をインストールしてみます。

Subversion は4つのプロトコルに対応しています。
  ・file (ローカルファイルへのアクセス)
  ・svn (Subversion 独自プロトコル)
  ・svn+ssh (svn プロトコルを ssh で暗号化)
  ・http/https (Apache を使用)

オープンソースプロジェクトでは http/https を使用することが多いように思えますが、今のところ Apacheのインストールは考えていないこととノートPCからも使用する (かもしれない) ことから、svn+ssh による環境構築を行います。
また、リポジトリ (ソースの格納場所) はプロジェクト毎に作成することとします。

1. Subversion のインストール

CentOS のインストール時に Subversion もインストール済みの場合、この項は飛ばしていただいて結構です。
もしインストール時の記憶があいまいでしたら rpm コマンドでインストール有無を確認可能です。

$ su -
# rpm -qa subversion
subversion-1.4.2-4.el5_3.1

rpm コマンドの結果が何も復帰しない場合は、yum コマンドでインストールを行います。

# yum install subversion.x86_64

(*)「yum install subversion」とした場合、32bit版もインストールされるので注意が必要です。

2. リポジトリの作成

Subversion のインストール完了後、リポジトリ (ソースの格納場所) の作成を行います。
最初にリポジトリ用ディレクトリを作成し、それを Subversion に登録する手順となります。
リポジトリの格納先は /var/svn/repos/hello (/var/svn/repos の hello プロジェクト) とします。

# mkdir -p /var/svn/repos/hello
# svnadmin create /var/svn/repos/hello

svnadmin コマンドを実行すると Subversion 用のディレクトリ/ファイル群が hello 配下に作成されます。

# ls /var/svn/repos/hello/
README.txt conf dav db format hooks locks

(*) 青字はディレクトリです。

3. アクセス権の設定

hello リポジトリは root で作成したため、このままでは他のユーザから更新ができません。
この問題を回避するために、リポジトリアクセス用のグループ「svn」を作成し、リポジトリ利用者には svn グループに所属してもらうことにします。

# groupadd svn
# usermod -G svn [ユーザID]

また、/var/svn 以下の所有グループの変更と write 権限の付与を行います。

# chgrp -R svn /var/svn
# chmod -R g+w /var/svn

4. リポジトリの構築 (import)

一般的に Subversion のプロジェクト構成は以下とした方がよいと言われています。
  PROJECT
   + trunk (メイン)
   + branches (ブランチ用)
   + tags (タグ用)
従わない理由はありませんので、上記構成で構築 (import) を行います。

最初に import 元となる WORK ディレクトリを作成します。
場所はどこでも構いません。(この例では ~/ 配下に作成しています)

$ mkdir ~/svn_test
$ mkdir ~/svn_test/trunk
$ mkdir ~/svn_test/branches
$ mkdir ~/svn_test/tags

作成した WORK ディレクトリを svn コマンドを使用して import します。

$ cd ~/svn_test
$ svn import svn+ssh://localhost/var/svn/repos/hello/ -m "first import"

svn コマンドは
  「svn+ssh」プロトコルを使用して
  「localhost」サーバの
  「/var/svn/repos/hello」プロジェクトに
  「first import」というコメントをつけて
  「import」を行う
という意味になります。
「-m」オプションはコメントを意味します。

(*) ファイルの追加や更新方法は、「Subversionの使いかた」を参照してください。

[ END ]

Eclipse JUnitプラグインの使い方 (JUnit 4) 編

JUnitプラグインは、プログラムの単体テスト (ユニットテスト) を自動化するためのplug-inです。
Eclipse IDE for Java EE Developers には標準で入っているため、インストールをすることなく使用可能です。

JUnitプラグインは「JUnit 3」と「JUnit 4」に対応しています。
これまで JUnit 4 を使用したことがなかったため、今回は、簡単に JUnit 4 による JUnitプラグインの使いかたをまとめてみました。

(*) JUnit 4 についてはこちらを参照させていただきました。

ちなみに JUnit 3 とのおもな違いは、テストケースをアノテーションで指定するようになったことのようです。(他にも色々あるようですが。。。)

1. テスト対象のクラス

単体テストを行うためには、当然テスト対象となるクラスが必要となります。
今回は以下のクラスを用意しました。

SampleUtility.java

package test;

public class SampleUtility {

    public static final int MORNING = 1;
    public static final int DAYTIME = 2;
    public static final int NIGHT   = 3;


    public String getJapaneseHello(int time) {

        String hello = null;

        switch (time) {
        case MORNING:
            hello = "おはよう";
            break;
        case DAYTIME:
            hello = "こんにちわ";
            break;
        case NIGHT:
            hello = "こんばんわ";
            break;
        default:
            throw new IllegalArgumentException("time: " + time);
        }

        return hello;
    }
}

(*1) JavaDoc は省略しています。
(*2) エラーとするため、「こんにち」「こんばん」はあえて間違えてます。念のため。

2. 単体テスト用クラス (テストケース) の作成

SampleUtility.java を選択した状態で右クリックメニューから「新規」-「JUnit テスト・ケース」を選択すると、SampleUtility.java 用のテストケース作成用画面が表示されます。

20100520_01

今回は次のように指定しました。
  ・「新規 JUnit 4 テストケース」項目にチェック
  ・「パッケージ」項目を「junit.test」に変更
  ・「メソッドスタブ」項目を4項目全てチェック

「次へ」ボタンを選択すると、テスト対象メソッドを選択する画面に遷移します。

20100520_02

スーパークラスの Java.lang.Object は単体テスト不要なため、SampleUtility のみを選択します。
「完了」ボタンで SampleUtility.java 専用のテストケースの雛型 SampleUtilityTest.java が作成されます。

初回のみビルドパス追加確認画面が出ますので、JUnit 4 ライブラリを追加してください。

20100520_03

SampleUtilityTest.java に自動作成されたメソッドは以下の5つです。
  ・public static void setUpBeforeClass() throws Exception;
  ・public static void tearDownAfterClass() throws Exception;
  ・public void setUp() throws Exception;
  ・public void tearDown() throws Exception;
  ・public void testGetJapaneseHello();

testGetJapaneseHello() メソッドが SampleUtility#getJapaneseHello(int) 用のテストケースで、テスト対象のメソッド数分作成されます。
また、他の4メソッドは、「メソッドスタブ」にチェックしたため作成されました。

この雛型から次のテストケースを作成しました。

SampleUtilityTest.java

package junit.test;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import test.SampleUtility;

public class SampleUtilityTest {

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        System.out.println("setUpBeforeClass()");
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        System.out.println("tearDownAfterClass()");
    }

    @Before
    public void setUp() throws Exception {
        System.out.println("setUp()");
    }

    @After
    public void tearDown() throws Exception {
        System.out.println("tearDown()");
    }

    @Test
    public void testGetJapaneseHelloMorning() {
        System.out.println("testGetJapaneseHelloMorning()");
        SampleUtility util = new SampleUtility();
        assertEquals("おはよう", util.getJapaneseHello(SampleUtility.MORNING));
    }

    @Test
    public void testGetJapaneseHelloDayTime() {
        System.out.println("testGetJapaneseHelloDayTime()");
        SampleUtility util = new SampleUtility();
        assertEquals("こんにちは", util.getJapaneseHello(SampleUtility.DAYTIME));
    }

    @Test
    public void testGetJapaneseHelloNigth() {
        System.out.println("testGetJapaneseHelloNigth()");
        SampleUtility util = new SampleUtility();
        assertEquals("こんばんは", util.getJapaneseHello(SampleUtility.NIGHT));
    }
}

(*1) JavaDoc は省略しています。
(*2) テストケースでは「こんにち」「こんばん」としています。
(*3) testGetJapaneseHello() は朝・昼・晩の3つに分けました。

3. テストケースの実行

SampleUtilityTest.java を選択した状態で右クリックメニューから「実行」-「JUnit テスト」を選択してください。単体テストが始まります。

初回の結果は、

20100520_04

と、あたりまえですが、3ケースのうち2ケースがエラーとなっています。

4. 修正と再テスト

SampleUtility#getJapaneseHello(int) について
  ・「こんにちわ」→「こんにちは」
  ・「こんばんわ」→「こんばんは」
と修正します。

そして再テスト。

20100520_05

今回は全てのテストケースが成功しました。

5. メソッドの実行順

SampleUtilityTest.java の全てのメソッドには System.out.println("...") を埋め込みました。
これらの実行順をログで確認してみます。

setUpBeforeClass()
setUp()
testGetJapaneseHelloMorning()
tearDown()
setUp()
testGetJapaneseHelloDayTime()
tearDown()
setUp()
testGetJapaneseHelloNigth()
tearDown()
tearDownAfterClass()

1. @BeforeClass アノテーションを定義したメソッドを実行
2. テストケース実行
 2.1. @Before アノテーションを定義したメソッドを実行
 2.2. @Test アノテーションを定義したメソッドを実行 (実際のテストケース)
 2.3. @After アノテーションを定義したメソッドを実行
 (*) 2.1.~2.3.を @Test アノテーションがなくなるまで繰り返し実行
3. @AfterClass アノテーションを定義したメソッドを実行

の順で実行されるようです。

[ END ]

Eclipse CheckStyleの設定 編

CheckStyle を有効にしてコーディングを進めていくと、気になる点がいくつか出てきます。
まずは下の画面をご確認ください。

HelloWrold.java

20100518_01

package-info.java

20100518_02

シンプルなソースであるにもかかわらず、合計5箇所に2種類のCheckStyle警告が出ています。

20100518_03

1つ目は 『sayHelloメソッドを final宣言 or abstract化 or 空メソッドとすること』で、2つめは 『JavaDoc の "。" を ". (ピリオド)" に変更すること』で解消可能なのですが、あまり必要性のないコーディング規約ではないでしょうか。
このあたりがデフォルトのCheckStyle定義の融通が聞かない部分のように思えます。

今回は、デフォルトのCheckStyle定義の中で、個人的にそこまで厳密にルール化する必要があるとは思えない設定を変更していきます。

1. オリジナル定義を作成

デフォルトの2つのCheckStyle定義「Sun Checks」「Sun Checks (Eclipse)」は変更することができないため、別途オリジナルのCheckStyle定義を作成します。

「ウィンドウ」-「設定」メニューから設定画面を表示します。
「CheckStyle」メニューの「グローバル・チェック構成」項目から、「Sun Checks」を選択して「コピー」ボタンを選択します。

20100518_04

チェック構成プロパティ画面が表示されますので、適当な名前 (ここでは「Sun Checks (Original)」としています) と説明を入力して「OK」ボタンを選択してください。

20100518_05

新規に作成した「Sun Checks (Original)」を選択して「構成」ボタンを選択すると、CheckStyle構成画面が表示されます。
この画面からチェック内容の変更を行います。

20100518_06

2. チェック内容の変更

No 警告メッセージ 項目 設定
1 メソッド 'xxx' は拡張するように設計されていません - abstractかfinalか空であるひつようがあります。 case:1 クラス設計 - 拡張のための設計 OFF
2 最初の一文はピリオドで終わらなければなりません。 case:2 JavaDocコメント - スタイルJavaDoc - checkFirstSentence OFF
3 パラメーター xxx は final でなければなりません。 case:3 その他 - Final パラメータ OFF
4 'xxx' がフィールドを隠しています。 case:4 コーディング問題 - 隠しフィールド OFF
5 'xxx' はマジックナンバーです。 case:5 コーディング問題 - マジック・ナンバー OFF

case:1 メソッド 'xxx' は拡張するように設計されていません - abstractかfinalか空であるひつようがあります

前述、HelloWorld.java の sayHello メソッドが該当します。

case:2 最初の一文はピリオドで終わらなければなりません

前述、HelloWorld.java の JavaDoc が該当します。(行の最後が「。」で終わっている。)

case:3 パラメーター xxx は final でなければなりません

メソッドのパラメタがfianl宣言を行っていない場合、警告メッセージが表示されます。

case:4 'xxx' がフィールドを隠しています

フィールド変数とローカル変数 (メソッドのパラメタ変数も含む) が同一の場合、警告メッセージが表示されます。

case:5 'xxx' はマジックナンバーです

数値リテラルを使用している場合、警告メッセージが表示されます。
ただし、-1, 0, 1, 2 は警告対象から除外されます。

3. プロジェクトの使用定義の変更

「プロジェクト」-「プロパティ」メニューから、CheckStyle定義に「Sun Checks (Original)」を指定します。

20100518_07

設定画面から「デフォルトとして設定」を行っておくと、以降作成するプロジェクトでこの変更を行う必要はありません。

[ END ]