グレースケール画像クラス MonoDouble のテスト作成(Matlab)

testing framework のインストール

Matlab の testing framework にもたくさんあるようだけど、本家 mathworks で紹介されていたので、matlab_xunitを使ってみました。ダウンロードしたものを展開して、パスを通すだけでよいようです。

テストの実行

テストを記述するフォルダを決めておき、そのフォルダで runtests とすると、自動的にテストを実行してくれます。私の場合は、testMono というフォルダを作ったので、以下のようにテストを実行しています。

cd testMono; runtests; cd ..

ほかにもっといいやり方があるのかもしれないけど。

testMonoDouble.m の一部を示します。他の言語の xunit と同様、test で始まるメソッドが自動的に呼ばれます。特にコメントはいらないですね。

% test_suite の宣言
function test_suite = testMonoDouble
    initTestSuite;
end

% setup はすべてのテストの前に呼ばれます.今回は,二つのオブジェクトをテスト用に準備します
function mds = setup
    y = 1.5.^(0:7)';
    x = (-1).^(0:7);
    md = MonoDouble(y * x);
    md2 = MonoDouble((rand(9, 7)-0.5)* 100, 16);
    mds = [md, md2];
end

% 自分の配列をコピーして,それを持つ新しいオブジェクトを作成して返します
% 関数には setup で用意された変数が渡されます.
function testMDCopy(mds)
    for md = mds
        assertEqual(md.buffer, md.copy.buffer);
    end
end

% 自分と同じ大きさの零行列を作成し,それを持つ新しいオブジェクトを作成して返します
function testMDZeros(mds)
    for md = mds
        correct = zeros(size(md.buffer));
        assertEqual(correct, md.zeros.buffer);
    end
end

function testMDDct(mds)
    for md = mds
        % 正解のオブジェクトを用意
        correct = MonoDouble(dct2(md.buffer), md.bits);
        % dct して新しいオブジェクトを作成(非破壊的メソッド)
        assertEqual(md.dct, correct);
        % 自分自身の行列を dct (破壊的メソッド)
        assertEqual(md.dct_, correct);
        % 本当に自分のデータが書き換わっているかどうかを確認します
        assertEqual(md, correct);
        % 正解のオブジェクトを用意
        correct = MonoDouble(idct2(md.buffer), md.bits);
        % idct して新しいオブジェクトを作成して返します(非破壊的メソッド)
        assertEqual(md.idct, correct);
        % 自分自身の行列を idct して返します(破壊的メソッド)
        assertEqual(md.idct_, correct);
        % 本当に自分のデータが書き換わっているかどうかを確認します
        assertEqual(md, correct);
    end
end

% 以下コメント省略
function testMDAbs(mds)
    for md = mds
        correct = MonoDouble(abs(md.buffer), md.bits);
        assertEqual(md.abs, correct);
        assertEqual(md.abs_, correct);
        assertEqual(md, correct);
    end
end

function testMDSign(mds)
    for md = mds
        correct = MonoDouble(sign(md.buffer), md.bits);
        assertEqual(md.sign, correct);
        assertEqual(md.sign_, correct);
        assertEqual(md, correct);
    end
end

function testMDRound(mds)
    for md = mds
        correct = MonoDouble(round(md.buffer), md.bits);
        assertEqual(md.round, correct);
        assertEqual(md.round_, correct);
        assertEqual(md, correct);
    end
end

function testMDClip(mds)
    for md = mds
        m = 2^md.bits - 1;
        tmp = round(md.buffer);
        tmp(tmp > m) = m;
        tmp(tmp < 0) = 0;
        correct = MonoDouble(tmp, md.bits);
        assertEqual(md.clip, correct);
        assertEqual(md.clip_, correct);
        assertEqual(md, correct);
    end
end

function testMDMulMat(mds)
    for md = mds
        mat = rand(size(md.buffer));
        correct = MonoDouble(md.buffer .* mat, md.bits);
        assertEqual(md.mulMat(mat), correct);
        assertEqual(md.mulMat_(mat), correct);
        assertEqual(md, correct);
    end
end

function testMDMul(mds)
    for md = mds
        other = MonoDouble(rand(size(md.buffer)), md.bits);
        correct = MonoDouble(md.buffer .* other.buffer, md.bits);
        assertEqual(md.mul(other).buffer, correct.buffer);
        assertEqual(md.mul_(other), correct);
        assertEqual(md, correct);
    end
end

function testMDAddMat(mds)
    for md = mds
        mat = rand(size(md.buffer));
        correct = MonoDouble(md.buffer + mat, md.bits);
        assertEqual(md.addMat(mat), correct);
        assertEqual(md.addMat_(mat), correct);
        assertEqual(md, correct);
    end
end

function testMDAdd(mds)
    for md = mds
        other = MonoDouble(rand(size(md.buffer)), md.bits);
        correct = MonoDouble(md.buffer + other.buffer, md.bits);
        assertEqual(md.add(other).buffer, correct.buffer);
        assertEqual(md.add_(other), correct);
        assertEqual(md, correct);
    end
end

function testMDImwriteImread(mds)
    for md = mds
        md.clip_;
        md.imwrite('test.tif');
        read = MonoDouble.imread('test.tif', md.bits);
        assertEqual(md.buffer, read.buffer);
    end
end

function testMDIterate(mds)
    for md = mds
        m = md.buffer;
        md.iterateStart_
        for r=0:md.height-1
            for c=0:md.width-1
                assertEqual(md.value, m(r+1, c+1));
                md.next_;
            end
        end
    end
end

function testMDBlock(mds)
    % 8x8 : block 4x3
    md = mds(1);
    m = md.buffer;
    md.setBlockSize_(4, 3);
    assertEqual(md.blockHeight, 4);
    assertEqual(md.blockWidth, 3);
    assertEqual(md.nowx, 0);
    assertEqual(md.nowy, 0);
    assertEqual(md.getBlock_.buffer, m(1:4, 1:3));
    assertEqual(md.next_, 1);
    assertEqual(md.nowx, 3);
    assertEqual(md.nowy, 0);
    assertEqual(md.getBlock_.buffer, m(1:4, 4:6));
    assertEqual(md.next_, 1);
    assertEqual(md.nowx, 6);
    assertEqual(md.nowy, 0);
    assertEqual(md.getBlock_.buffer, m(1:4, 7:8));
    assertEqual(md.next_, 1);
    assertEqual(md.nowx, 0);
    assertEqual(md.nowy, 4);
    assertEqual(md.getBlock_.buffer, m(5:8, 1:3));
    assertEqual(md.next_, 1);
    assertEqual(md.nowx, 3);
    assertEqual(md.nowy, 4);
    assertEqual(md.getBlock_.buffer, m(5:8, 4:6));
    assertEqual(md.next_, 1);
    assertEqual(md.nowx, 6);
    assertEqual(md.nowy, 4);
    assertEqual(md.getBlock_.buffer, m(5:8, 7:8));
    assertEqual(md.next_, 0);
    assertEqual(md.nowx, -1);
    assertEqual(md.nowy, -1);
    assertEqual(md.getBlock_, zeros(0,0));
    
    % 9x7 : block 4x3
    md = mds(2);
    m = md.buffer;
    md.setBlockSize_(3, 4);
    assertEqual(md.blockHeight, 3);
    assertEqual(md.blockWidth, 4);
    assertEqual(md.nowx, 0);
    assertEqual(md.nowy, 0);
    assertEqual(md.getBlock_.buffer, m(1:3, 1:4));
    assertEqual(md.next_, 1);
    assertEqual(md.nowx, 4);
    assertEqual(md.nowy, 0);
    assertEqual(md.getBlock_.buffer, m(1:3, 5:7));
    assertEqual(md.next_, 1);
    assertEqual(md.nowx, 0);
    assertEqual(md.nowy, 3);
    assertEqual(md.getBlock_.buffer, m(4:6, 1:4));
    assertEqual(md.next_, 1);
    assertEqual(md.nowx, 4);
    assertEqual(md.nowy, 3);
    assertEqual(md.getBlock_.buffer, m(4:6, 5:7));
    assertEqual(md.next_, 1);
    assertEqual(md.nowx, 0);
    assertEqual(md.nowy, 6);
    assertEqual(md.getBlock_.buffer, m(7:9, 1:4));
    assertEqual(md.next_, 1);
    assertEqual(md.nowx, 4);
    assertEqual(md.nowy, 6);
    assertEqual(md.getBlock_.buffer, m(7:9, 5:7));
    assertEqual(md.next_, 0);
    assertEqual(md.nowx, -1);
    assertEqual(md.nowy, -1);
    assertEqual(md.getBlock_, zeros(0,0));
end

次回,これが通るクラスを実装します.