2016-10-25 7 views
0

私は最近、私が取り組んでいるプロジェクトのためのいくつかの長方形ビンパッキングアルゴリズムを実装しました。私は多少の矩形を生成して結果を見ることでやや素朴にテストしてきましたが、もっと体系的に検討したいと思います。ユニットテストの長方形パッキングアルゴリズムの方法

class RectPacker 
{ 
public: 
    RectPacker(int width, int height); 
    virtual ~RectPacker(); 

    ////// 
    /// \brief fit a rectangle into the available space 
    /// 
    /// \param[in] width, height size of the rectangle to be fitted 
    /// \param[out] x, y   position where the rectangle was fitted (disregard if function returns false) 
    /// \param[out] rotated   whether or not the rectangle was rotated during the fitting 
    /// \return true if position for the rectangle could be found, false if rectangle could not be fitted. 
    /// 
    virtual bool findBestPosition(int width, int height, int& x, int& y, bool& rotated) = 0; 

    ////// 
    /// \brief clear the rectangle packer 
    /// 
    /// Resets the packer to an empty state. This is usefull when you want to free up space. 
    /// Since just freeing space will the space fragmented and degrade packing performance 
    /// it is usually better to just clear the entire packer and repack all the remaining 
    /// rectangles. 
    /// 
    virtual void clear() = 0; 
}; 

基本的には、ビンサイズでパッカーを初期化:

公開されていますインターフェイスは、次のようになります。 findBestPositionを呼び出すたびに、そのビンのチャンクが一杯になるまで矩形に割り当てられ、それ以上は収まらなくなります(この場合、メソッドはfalseを返します)。

システムインターフェースが非常に小さいので、アルゴリズムはかなり複雑で、内部状態を検査することはできません。これについてユニットテストを書くにはどうすればいいですか?

私の直感は、ランダムに生成された矩形を大量に打ち込むだけでよいことを示しています。私は返品された付属品のリストを保持し、それらがビンの範囲内にあり、相互に分離しているかどうかをチェックします。しかし、縮退している特定のケース(片側にすべての長方形を積み重ね、80%以上の空白を残しておくなど)をテストしません。もちろん、アルゴリズムがフィッティングを拒否し始めるときに、許容される最大の廃棄率を定義して確認することもできます。

これにはいくつか不満な側面があります。

  • 私は許さ廃棄物の割合を設定しますどのように?それはひどく恣意的で、私には嫌な思いがするようです。それをあまりにも低く設定すると、誤検知が多すぎるため、あまりにも高く設定すると、アルゴリズムの問​​題を逃してしまいます。
  • 私は単体テストが決定論的で再現性があるのが好きです。ランダムなデータは正しく感じられません。しかし、もし私が不足しているもののリスクがあるたびに、同じ長方形のセットを使用すれば、
  • 返されたフィッティングを追跡し、それらを分析すると、テスト自体が複雑になり、エラーが発生しやすくなります。単体テストは単純に死んではいけません。
  • ある誤動作は、人間の目のデータを見るだけで明らかになります。アルゴリズムが「正常に動作している」ことを確認する方法が不明です。例えば、大きなギャップを残すか、効率を最大限にするために四角形を回転させることができないかもしれません。あるいは、それらをすべて間違った方向に回転させるかもしれません(符号エラー)...

私はテストする方法を知っていますそれは手作業ですが、そのためのテストスイートを書く方法は?私はこれをより困難にしていますか?私はそれをテストすることになると話している何をかなり確実決して思いません注意点が

+0

を挿入しようR1 =(ax Gr)xa、R2 = ax(a/Gr)、... –

答えて

1

は、ここで私はこのことを考えて行くだろう方法は次のとおりです。

なぜあなたはユニットテストを書いていますか?私の理解では、単体テストはコードが何か正しいことを確認することです。特定の長方形の領域でビンをパックします。その差より大きな面積の四角形をパックしてみてください。フィットしますか?それはしないでください。単一の矩形をパックします。それは端にありますか?これは、常に保持する必要がある単純な制約を探す場所です。リファクタリングを台無しにしたり、何かを見落としたりすると、それを捕まえることができます。アルゴリズムがあなたの宇宙の物理学にどのように違反することができますか?それを確認する最も簡単な方法は何ですか?

どのようによくあなたのアルゴリズムが実行する別の懸念です。これはベンチマークであり、単体テストではありません。あなたは無作為よりもうまくいくのですか?他のビンパッキングアルゴリズムとの比較はどうですか?

テストとベンチマークは2つの異なる目的を持っており、私はそれらを別々に扱います。

アドレッシングの特定のポイント:

しかし、私は長方形の同じセットを毎回使用している場合、私は不足しているものを危険にさらします。

すべてをテストすることはできません。あなたが考えることができるすべてのケースを扱います。新しいことが登場すれば、レッスンは学びました。

どのように許可された廃棄率を設定しますか?

問題の文脈と文脈を見てください。あなたはどれくらいいい必要がありますか?他の人はどれくらいいいですか?

アルゴリズムが「正常に動作している」ことを確認する方法がわかりません。

特定の動作のための最小限の例を作成できます。正しい回転の問題を解決するには、「ワイド」ボックスを「背の高い」ビンに合わせてください。唯一の解決方法は回転させることです。または

| | 
| | 
| | 
|x | 
------ 

のようなものを構築し、一連の矩形を生成するために、[黄金比](https://en.wikipedia.org/wiki/Golden_ratio)を使用していないものの

xxxx 
+0

上記のようなコーナーケースと既知の出力を持つ静的なケースのいくつかに加えて、テストケースを作成しようとするマニュアル検査(開発またはテスト中)で問題が検出されたときはいつでも。まず、動作を刺激するテストケースを作成し、問題を修正します。これは回帰を回避するのに役立ちます。 – Peter