- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直潜伏在这里寻求帮助,现在我找不到当前问题的答案。
返回信息
我正在编写一些单元测试(是的!)。我有40个实现接口的对象。该接口中的一个函数接受两个参数,一个Rectangle和一个Rectangle数组:public function foobar(foo:Rectangle, bar:Array/*Rectangle*/):void;
我想为这40个对象编写测试。为确保测试所有可能性,我需要在foo和bar(长度和内容)不同的地方进行测试。所以foo的x个数和foo中Rectangle的1个数。
每个实现该接口的对象都在运行一种算法,该算法将对bar中的每个Rectangle进行一些计算并更改其属性。每种算法都会产生截然不同的结果。
如果我选择有10个可能的foo对象,以及bar数组的10个可能的对象,我最终将写成千上万!测试。我不想手写数千个测试。
问题
对我而言,编写一个可以接收可能对象的算法,并对所有可能产生结果的可能配置进行欠缺测试的算法,是否会太落后?然后我返回并手动检查所有结果是否正确?这是进行单元测试的错误方法吗?
运行产生结果的算法是错误的,然后,手动检查输出?
我的另一种想法是,我向算法提供了可能的对象,并且它吐出了一些针对测试工具格式化的xml或json,然后我通过了每个测试,填写了缺少的断言值,然后通过它们来进行输入?
我的另一个计划是编写一种算法,该算法接受一个foo Rectangle列表和一个可能在bar中使用的Rectangle列表,并让该算法以与我的测试工具(包括断言)一起使用的格式生成JSON。由于产生JSON的算法不会知道这些断言,因此在通过测试工具将其发送之前,我会先将其写入。
这是常见的做法吗?
感谢您的任何反馈:)
最佳答案
给出一个好的答案并不容易,不知道有关您在实现中执行的计算类型的任何细节,但是我很佩服您愿意进行单元测试,所以无论如何我都会尽力而为,希望答案不会太长。 ;)
0.期望很高?
老实说,可能没有一个与您的问题完全相符的答案-许多方法可以正确完成工作,并且适用于单元测试的唯一基本规则是,它们应该可靠地帮助您证明您的系统是稳定的。如果他们不这样做,那么您就不必费心编写它们。但是如果可以做到这一点,可以通过创建具有一百万行不同输入和输出值组合的Excel工作表,然后将CSV格式的工作表馈送到单元测试中的for循环中来实现...
好的,也许有更好的方法。但是最终,这一切都取决于您要完成此操作的程度,以及您愿意为完成更好的测试而偏离所做的工作的程度。
1.准备一些聪明的评论
根据我在各行中所读到的内容,您没有花太多时间考虑可测试性,因为在编写测试之前已经编写了代码。可悲的是,这实际上并不是进行单元测试的最佳方法:添加到生产代码中的每一行都应始终在失败的单元测试中覆盖,甚至在编写它之前。只有这样,您才能始终确保系统正常运行-并且始终可以测试!听起来很累吗?一旦您习惯了,它就不是。
我不会在基础方面打扰您,但如果您真的很认真地对待单元测试,请让我建议您开始将TDD应用于所有 future 项目:首先,也许要观看cleancoders.com上的TDD情节-Bob叔叔这样做解释这些事情的方法比我做得更好,而且他很有趣(尽管他的演示是用Java编写的,但这不应该是个大问题-TDD的基本原理适用于所有语言)。
同时,我仍会根据您的问题做一些聪明的评论。告我 ;)
2.智能资产备注1:如何测试?
确保记住的测试目标是证明您正在测试的代码正确运行,而不是针对每种可能的参数组合重复进行验证。您应始终将断言的数量保持在最低限度,以证明您的代码正确。
然后,这将回答您的第一个问题:您应该只进行一次测试,以证明所测试的每种算法的正确性。输入和输出值的不同组合可用于该测试中的断言。
为每个算法添加更多测试的唯一原因是在测试失败时,即,如果将null
作为参数传递,或者违反约束的任何事物都会发生什么。每次在发生故障时抛出错误时,都应在单独的测试中进行测试。
但是,更复杂的是选择开始编写测试的抽象级别。通常不必为类中的每个方法编写测试,尤其是对于私有方法。这是应用TDD的另一个原因-它使您可以从外部考虑要执行的操作,即您测试系统的一部分应该执行的操作,而不是测试每个实现细节。当您在编写代码之前进行测试时,很容易在这里和那里添加测试,因为您注意到程序已经扩展并且事情变得更加复杂。在“事后”执行此操作总是要困难得多。
3.智能资产注释2:要测试什么?
程序设计的目标应该是,使您的单元与系统的其他部分分离开,尽可能。这意味着将一个事物组合应用于一个单元中的另一个事物组合可能不是一个好的设计。您应该只能测试要在测试单元中实现的代码,并将其与所有其他内容分开。这表示
bar
Rectangle的坐标值对
foo
数组的所有成员重复应用相同的计算。这意味着您实际上在方法中做了两件事:a)遍历
bar
数组,以及b)应用公式:
public function foobar ( foo:Rectangle, bar:Array ) : void {
for each ( var rect:Rectangle in bar) {
// things done to rect based on foo
}
}
public function foobar ( foo:Rectangle, bar:Array ) : void {
for each ( var rect:Rectangle in bar) {
applyFooValuesToRect( foo, rect);
}
}
public function applyFooValuesToRect ( foo : Rectangle, rect : Rectangle ) : void {
// things done to rect based on foo
}
applyFooValuesToRect
方法-突然使编写测试变得更加容易。
foo
应用于所有
bar
,一种匹配某些条件,仅应用于正匹配,也许一个基于每个
bar
值对foo进行一系列计算,一个可以使用两个公式,而不是一个,等等。如果其中任何一个适用于您的项目,则可以使用
Strategy pattern极大地改善您的API,并降低复杂性。对于40个变体中的每个变体,将实际公式设为实现通用
Formula
接口的单独类:
public interface Formula {
function applyFooToBar (foo:Rectangle, bar:Rectangle) : Rectangle;
}
public class FormulaOneImpl implements Formula {
public function applyFooToBar (foo:Rectangle, bar:Rectangle) : Rectangle {
// do things to bar
return bar;
}
}
public class FormulaTwoImpl implements Formula ... // etc.
Formula
类型的字段变量:
public class MyGreatImpl implements OriginalInterface {
public var formula:Formula;
//..
public function foobar (foo:Rectangle, bar:Array):void {
for each (var rect:Rectangle in bar) formula.applyFooToBar (foo, rect);
}
}
Formula
模拟对象所要做的就是验证是否调用了
applyFooToBar
,并返回为每个断言设置的预定值。这样,您可以确保在测试数组的迭代时确实没有在测试公式。
CriteriaMatcher
也是一种不错的策略,从...开始
关于actionscript-3 - 编写动态单元测试(flexunit)令人困惑。我如何使它更具模块化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9627483/
很抱歉新手的问题,但是: 我最近才发现“=”运算符不只是处理对象/等等。值(value),也是引用。这很酷,但我认为这对变量来说是不一样的,它不会在存储整数或 float 的变量之间创建引用。后来我觉
我是一名优秀的程序员,十分优秀!