【问题标题】:How to unit test rectangle packing algorithm如何对矩形打包算法进行单元测试
【发布时间】:2016-10-27 04:55:53
【问题描述】:

我最近为我正在从事的项目实施了一些矩形箱包装算法。我一直在通过生成大量矩形并查看结果来稍微天真地对其进行测试,但我想更有条理地进行测试。

公开的界面如下所示:

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;
};

基本上你用一个 bin 大小来初始化打包器。对 findBestPosition 的每次调用都会将该 bin 的一部分分配给一个矩形,直到它被填满并且不能再容纳(在这种情况下,该方法将返回 false)。

那么,鉴于系统接口如此之小,算法相当复杂,我无法检查内部状态,我该如何为此编写单元测试?

我的直觉告诉我,我可以用大量随机生成的矩形来敲击它。我会保留一份退回配件的清单,并检查它们是否都在垃圾箱的范围内并且相互不相交。但是,这并不能测试某些退化的情况(例如将所有矩形堆叠在一侧并留出 >80% 的空间)。当然,我可以尝试定义最大允许的浪费百分比,并在算法开始拒绝配件时检查它。

这有几个不满意的方面:

  • 如何设置允许的废物百分比?对我来说,这似乎非常武断和一厢情愿。将其设置得太低会导致太多误报,设置得太高会错过算法中的问题。
  • 我希望我的单元测试具有确定性和可重复性。随机数据感觉不对。但是,如果我每次冒着丢失东西的风险都使用同一组矩形。
  • 通过跟踪退回的配件并对其进行分析,测试本身变得如此复杂以至于容易出错。单元测试应该非常简单。
  • 某些不当行为只有通过用一双人眼查看数据才能显现出来。不确定如何检查算法是否“表现良好”。例如,它可能会留下很大的间隙,或者它可能无法旋转矩形以获得最大效率,或者它可能会以错误的方式旋转它们(符号错误)并以这种方式浪费空间......

我知道如何手动测试它,但是如何为此编写测试套件?我是不是让这件事变得更难了?

【问题讨论】:

  • 虽然没有使用Golden ratio通过使用螺旋的属性R1 = (a x Gr) x a, R2 = a x (a / Gr), ...跨度>

标签: c++ unit-testing


【解决方案1】:

需要注意的是,当谈到测试时,我一直不太清楚自己在说什么,以下是我的想法:

为什么要编写单元测试?据我了解,单元测试是为了确保代码做正确的事情。用一定面积的矩形包装一个箱子。尝试打包一个面积大于差异的矩形。合身吗?它不应该。打包一个矩形。是不是在边缘。这是您寻找应该始终保持的简单约束的地方,因此如果您搞砸了重构或忽略了某些东西,您可以抓住它。该算法怎么会违反你的宇宙物理学,你检查的最简单的方法是什么?

您的算法的性能如何是另一个问题。这是基准测试,而不是单元测试。你做得比随机更好吗?它与其他装箱算法相比如何?

测试和基准测试有两个不同的目的,我将分别对待它们。

解决具体问题:

但如果我每次冒着丢失东西的风险都使用同一组矩形。

您无法测试所有内容。处理所有你能想到的情况。如果有新的东西出现,吸取教训。

如何设置允许的废物百分比?

查看可用的文献和问题的背景。你需要有多好?其他人有多好?

不确定如何检查算法是否“表现良好”。

您可以为特定行为构建最少的示例。对于正确的旋转问题,将“宽”框放入“高”箱中,因此唯一的解决方案是旋转。或者构建类似的东西

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

并尝试插入

xxxx

【讨论】:

  • 除了前面提到的极端案例,以及一些具有已知输出的静态案例之外,还可以在您的手动检查(在开发或测试期间)发现问题时尝试创建测试案例。首先制作一个刺激行为的测试用例,修复问题。这将有助于避免回归。
猜你喜欢
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 2019-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多