【问题标题】:Unit test proper data structure creation单元测试正确的数据结构创建
【发布时间】:2009-09-12 12:34:54
【问题描述】:

如何测试数据结构是否正确构建?我正在实现一种修改后的基数树,并且想知道如何检查您的数据结构是否正确构建。

考虑TreeNode {String, Int} 节点的树。 您总是希望将新子节点附加到值等于 0 的最深节点,如下例所示:

根,0 - Child_1, 5 - Child_2, 0 - Child_3, 1

问题是,如果树形结构按照您的意愿构建,如何进行单元测试? TreeNode 只有一种方法,即insert

到目前为止,我的想法是编写TreeVisitor,它将遍历树并将每个节点转换为字符串。 上面示例中的树可能如下所示:

[根, 0 [Child_1, 5][Child_2, 0 [Child_3, 1]]]

知道构建树的算法,如果我知道我要插入什么元素,我可以手动创建这样的字符串。我的单元测试看起来像这样(使用相同的示例)。

TreeNode root = new TreeNode("Root", 0);
root.insert(new TreeNode("Child_1", 5));
root.insert(new TreeNode("Child_2", 0));
root.insert(new TreeNode("Child_3", 1));
TreeVisitor visitor = new TreeVisitor();
String expected = "[Root, 0 [Child_1, 5][Child_2, 0 [Child_3, 1]]]";
asssertEquals(expected, visitor.visit(root));

我觉得这不是最好的方法。首先,一旦访问者发生变化,所有测试都会失败(只需将[ ] 更改为( ))。此外,这种方法允许我测试非常小的树(我可以手动计算的那么大)。你会如何测试更大的?

一般问题是,如何编写测试来检查数据结构是否正确构建

我想我可能把整个测试想法弄错了,因为我刚从十几个教程中测试 .Sum(a, b) 是否按预期工作:-)

【问题讨论】:

    标签: java unit-testing tree tdd


    【解决方案1】:

    这看起来像是一个实际的测试驱动设计案例。只有“插入”方法的接口是不可测试的,因为它也不可用。建造一棵树,而无法看到或做任何事情,你建造的树不会让你到任何地方。

    确定您希望客户端如何访问树(访问方法、访问者界面或其他)。然后通过它们进行测试。

    如果存在您无法通过公共接口轻松获得的内部复杂性(即,树更像 Java TreeMap,而不是放入 TreeView 中的树类型),您可以使用:

    • 断言和不变量
    • 类似暴露的东西 debugVerifyTree 方法。
    • 蛮力:插入 36542 个伪随机项,使用覆盖工具检查是否覆盖所有情况。

    无论哪种方式,在您编写测试时,请务必提出“如果此测试失败,此代码的任何客户端是否会关心此问题?”。如果没有,请删除它。

    【讨论】:

      【解决方案2】:

      也许您可以用您自己的子类替换单元测试中 TreeNode 的实现,该子类公开方法,让您递归地检查当前子类集。这些方法将添加到 TreeNode 实现以帮助进行单元测试,并且不会替换其现有功能,因此您仍然可以进行有效的测试。

      【讨论】:

        【解决方案3】:

        我通常最终做的是使值或名称指示您正在测试的事物。因此,在树的情况下,名称可能表示深度和子索引。

        TreeNode root = new MyTreeNode("0.0", 0);
        root.insert(new MyTreeNode("1.0", 5));
        root.insert(new MyTreeNode("1.1", 0));
        root.insert(new MyTreeNode("2.0", 1));
        verify(root, 0, 0);
        ...
        public void verify(TreeNode node, int depth, int index) {
           verifyName(node, depth, index);
           int numChildren = node.getChildCount();
           depth++;
           for (int i = 0; i < numChildren; i++) {
              verify(node.getChildAt(i), depth, i);
           }
        }
        public void verifyName(TreeNode node, int depth, int index) {
           StringBuilder expectedName = new StringBuilder();
           expectedName.append(depth).append('.').append(index);
           assertEquals("Tree node not in expected place",
                        expectedName.toString(), node.getName());
        }
        

        现在我可以想象测试一棵相当大的树了。如果递归的深度有问题,那么您可以使用堆栈来解开递归方法。

        public void verify(TreeNode root) {
           Stack<TreeNode> toBeVerified = new Stack<TreeNode>();
           verifyName(root, 0, 0);
           toBeVerified.push(root);
        
           while(!toBeVerified.isEmpty()) {
             TreeNode node = toBeVerified.pop();
             int depth = getDepth(node.getName()) + 1;
             int numChildren = node.getChildCount();
             for (int i = 0; i < numChildren; i++) {
                verifyName(node, depth, i);
                toBeVerified.push(node);
             }
           }
        }
        public int getDepth(String name) {
           return Integer.parseInt(name.substring(0, name.indexOf('.')));
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-05
          • 1970-01-01
          相关资源
          最近更新 更多