简体   繁体   English

Swift 中的等价测试

[英]Equatable Testing in Swift

I'm looking for suggestions on good practices to test the equality of swift objects我正在寻找有关测试 swift 对象相等性的良好做法的建议

If I have a complex object with many properties it's easy to miss the equality implementation.如果我有一个具有许多属性的复杂对象,很容易错过相等的实现。

What are the good practices to enforce the equality implementation?执行平等实施的良好做法是什么?

More details: Of course, you can write tests to check that two value are equal when they should, but the problem here is that this can break easily.更多细节:当然,您可以编写测试来检查两个值是否应该相等,但这里的问题是这很容易破坏。 You have a struct in your project, after six months another developer adds a property to that struct.您的项目中有一个结构,六个月后,另一个开发人员向该结构添加了一个属性。 Assume that he forgets to add the property to the equality.假设他忘记将属性添加到等式中。 The equality still works, the tests pass but your app will break when only that property changes.相等性仍然有效,测试通过,但只有该属性更改时,您的应用程序才会中断。 My question is, there is a way to avoid this problem?我的问题是,有没有办法避免这个问题?

In a non trivial app is really easy to end up having model objects with 10 values, and use nested model objects.在一个非平凡的应用程序中很容易最终拥有具有 10 个值的模型对象,并使用嵌套的模型对象。 So how can I keep under control the equality of my model objects?那么我怎样才能控制我的模型对象的平等呢? How can I reduce the human error risk in the equality implementation?如何降低平等实施中的人为错误风险?

Possible solution: One solution I have in mind is to write a script that looks at compile time for classes and struct that conform to a certain protocol可能的解决方案:我想到的一个解决方案是编写一个脚本,查看符合特定协议的类和结构的编译时间

Diffable : Equatable {}

For all the classes/structs that adopt Diffable I'll check for the existance of a test file, ie:对于所有采用Diffable的类/结构,我将检查测试文件的存在,即:

For the class Foo I'll look for a test class Foo_Tests_Diffable对于Foo类,我将寻找一个测试类Foo_Tests_Diffable

than for all the properties inside Foo I'll check for the existance of a test function that conform to the following name pattern对于Foo中的所有属性,我将检查是否存在符合以下名称模式的测试函数

test<property name>Diffable

ie: IE:

class Foo : Diffable {
   var title: String
   var color: UIColor
   var tag: Tag
}

I'll check for the following tests inside Foo_Tests_Diffable我将在Foo_Tests_Diffable中检查以下测试

func testTitleDiffable {
// Test
}

func testColorDiffable {
// Test
}

func testTagDiffable {
// Test
}

If all the script finds all the expected tests than the compile step pass, otherwise it fails如果所有脚本都找到了所有预期的测试而不是编译步骤通过,否则失败

But this solution it's time consuming and I don't know if I'll be able to implement it, so any suggestion is welcome但是这个解决方案很耗时,我不知道我是否能够实现它,所以欢迎任何建议

I would create unit tests specifically for this purpose.我会专门为此目的创建单元测试

class YourObjectEquatableTests: XCTestCase
{
    func testPropertyOne()
    {
        var object1 = /* ... */
        var object2 = /* ... */

        object1.propertyOne = nil
        object2.propertyOne = nil

        XCTAssertEqual(object1, object2)
        object1.propertyOne = "different value"
        XCTAssertNotEqual(object1, object2)

        /* etcetera */
    }

    func testPropertyTwo()
    {
        /* ... */
    }
}

Note: if you write your test cases before implementing the Equatable details, you're actually doing TDD which is very cool!注意:如果你在实现 Equatable 细节之前编写测试用例,你实际上是在做 TDD,这非常酷!

I didn't try it a lot but Swift has Reflection capabilities.我没有尝试很多,但 Swift 具有反射功能。

https://appventure.me/2015/10/24/swift-reflection-api-what-you-can-do/ https://appventure.me/2015/10/24/swift-reflection-api-what-you-can-do/

So in your case, you can mirror a class and then put some conditions in your test.所以在你的情况下,你可以镜像一个类,然后在你的测试中加入一些条件。

for example, you can set a fix number or attribute or methods for a class in your test.例如,您可以为测试中的类设置修复编号或属性或方法。

let nbAttributes = 6

and then check it:然后检查它:

aMirror.children.count

I wrote a simple example in the playground and if I add a method variable, the children count increases.我在操场上写了一个简单的例子,如果我添加一个方法变量,孩子的数量就会增加。 I don't know if it's possible to check the methods though.我不知道是否可以检查方法。

class toto{
  var io = 9
  var tutu = "yo"
  func test(){

  }
}

let toto1 = toto()

let aMirror = Mirror(reflecting: toto1)
aMirror.children.count

another link: Reflection in swift 2另一个链接: swift 2 中的反射

Hope that helps :)希望有帮助:)

Yes, expanding on @Mikael's answer, you should probably use Reflection.是的,扩展@Mikael 的答案,您可能应该使用反射。

An example would be:一个例子是:

String(reflecting: obj1) == String(reflecting: obj2)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM