1

我正在用PHPunit测试我的代码。我的代码有几种排序方法:按名称、年龄、计数和随机。下面是按计数排序的实现和测试。这些都是非常微不足道的。

class Cloud {
  //...
  public function sort($by_property) {
    usort($this->tags, array($this, "cb_sort_by_{$by_property}"));
    return $this;
  }

  private function cb_sort_by_name($a, $b) {
    $al = strtolower($a->get_name());
    $bl = strtolower($b->get_name());
    if ($al == $bl) {
      return 0;
    }
    return ($al > $bl) ? +1 : -1;
  }

  /**
   * Sort Callback. High to low
   */
  private function cb_sort_by_count($a, $b) {
    $ac = $a->get_count();
    $bc = $b->get_count();
    if ($ac == $bc) {
      return 0;
    }
    return ($ac < $bc) ? +1 : -1;
  }
}

经测试:

  /**
   * Sort by count. Highest count first.
   */
  public function testSortByCount() {
    //Jane->count: 200, Blackbeard->count: 100
    //jane and blackbeard are mocked "Tags".
    $this->tags = array($this->jane, $this->blackbeard);

    $expected_order = array("jane", "blackbeard");
    $given_order = array();

    $this->object->sort("count");

    foreach($this->object->get_tags() as $tag) {
      $given_order[] = $tag->get_name();
    }

    $this->assertSame($given_order, $expected_order);
  }

但是现在,我想添加“随机排序”

  /**
   * Sort random.
   */
  public function testSortRandom() {
    //what to test? That "shuffle" got called? That the resulting array
    // has "any" ordering?
  }

实现可以是任何东西,从调用shuffle($this->tags)usort随机返回 0、-1 或 +1 的回调。性能是一个问题,但可测试性更重要。

如何测试数组是随机排序的?AFAIK 很难存根全局方法,例如shuffle.

4

3 回答 3

1

假设你正在使用shuffle你的方法应该是这样的

sortRandom() {
 return shuffle($this->tags);
}

好吧,您不需要测试键是否被洗牌,但是否仍然返回数组。

function testSortRandom(){
    $this->assertTrue(is_array($this->object->sortRandom()));
}

您应该测试您的代码,而不是 php 核心代码。

于 2015-01-28T16:06:57.543 回答
0

在任何有意义的意义上,这实际上是不可能的。如果您的列表中只有几个项目,那么完全有可能按随机排序确实看起来像按任何给定字段排序(并且碰巧它与按排序顺序相同的可能性如果您没有太多元素,任何其他领域都相当高)

如果您问我该操作是否实际上并未以任何方式操纵数据,则对排序操作进行单元测试似乎有点愚蠢。感觉就像是为了它而进行单元测试,而不是因为它实际上是在衡量某些东西是否按预期工作。

于 2013-01-02T21:12:21.937 回答
0

我决定用一个全局包装器来实现它:

class GlobalWrapper {
  public function shuffle(&$array);
    shuffle($array);
  }
}

在排序中,我shuffle通过该包装器调用:

public function sort($by_property) {
  if ($by_property == "random") {
    $this->global_wrapper()->shuffle($this->tags);
  }
  //...
}

然后,在测试中,我可以模拟它GlobalWrapper并为感兴趣的全局函数提供存根。在这种情况下,我感兴趣的只是方法被调用,而不是它的输出[1]。

 public function testSortRandomUsesShuffle() {
   $global = $this->getMock("GlobalWrapper", array("shuffle"));
   $drupal->expects($this->once())
     ->method("shuffle");
   $this->object->set_global_wrapper($drupal);

   $this->object->sort("random");
 }

[1] 实际上,我对此包装器也有单元测试,测试参数以及它执行引用调用的事实。此外,这个包装器已经实现(并被调用DrupalWrapper)以允许我对第三方(Drupal)提供的某些全局函数进行存根。这个实现允许我使用 a 传入包装器set_drupal()并使用drupal(). 在上面的例子中,我把这些set_global_wrapper()global_wrapper().

于 2013-01-03T09:42:21.773 回答