我正在构建一些类和代码来存储货币值并对其进行算术运算。我最初使用Doubles,但由于算术错误而转换为Decimal。
我正在尝试找到针对使用Decimal类型的函数运行单元测试的最佳方法。
考虑position.totalCost
是一个十进制类型。
XCTAssertEqual(position.totalCost, 3571.6, accuracy: 0.01)
此代码无法编译,因为Decimal不符合FloatingPoint。 XCTAssertEqual要求参数为Doubles或Floats。
我通过以下操作解决了这个问题:
XCTAssertTrue(position.totalCost == 3571.6)
这确实有效,但是如果在单元测试期间出现错误,我会得到模糊的消息:
XCTAssertTrue failed
而不是更有用的XCTAssertEqual failed: ("2.0") is not equal to ("1.0")
所以使用XCTAssertEqual是理想的。
潜在选项(作为新手,没有更好或更可行的线索)
编码我的Position类以将所有属性存储为Decimal,但使用计算出的属性来获取它们并将其设置为Doubles。
编写一个接受小数的自定义断言。这可能是最“正确”的路径,因为到目前为止,我使用Decimals遇到的唯一问题是XCT断言无法接受它们。
写一个愚蠢的十进制扩展名,它将返回一个Double值。无论出于何种原因,Decimal类中都没有返回Double或Floag的属性或函数。
如果不需要,请不要将Decimal
转换为浮点,因为这会导致精度损失。如果要比较两个Decimal
值的准确性,可以使用Decimal.distance(to:)
函数,如下所示:
let other = Decimal(35716) / Decimal(10) // 3571.6
let absoluteDistance = abs(position.totalCost.distance(to: other))
let accuracy = Decimal(1) / Decimal(100) // 0.01
XCTAssertTrue(absoluteDistance < accuracy)
您真的需要指定accuracy
的0.01
吗?
由于省略了该参数,所以编译就很好。
struct Position {
let totalCost: Decimal
}
let position = Position(totalCost: 3571.6)
//passes
XCTAssertEqual(position.totalCost, 3571.6)
// XCTAssertEqual failed: ("3571.6") is not equal to ("3571.61")
XCTAssertEqual(position.totalCost, 3571.61)