onevcat / OneV-s-Den-Comments

0 stars 0 forks source link

2021/12/tca-2/ #29

Open utterances-bot opened 2 years ago

utterances-bot commented 2 years ago

TCA - SwiftUI 的救星?(二) | OneV's Den

在上一篇关于 TCA 的文章中,我们通过总览的方式看到了 TCA 中一个 Feature 的运作方式,并尝试实现了一个最小的 Feature 和它的测试。在这篇文章中,我们会继续深入,看看 TCA 中对 Binding 的处理,以及使用 Environment 来把依赖从 reducer 中解耦的方法。

https://onevcat.com/2021/12/tca-2/

Mephsito23 commented 2 years ago

前段时间刚把自己的应用用TCA 重构了一遍,今天就看到了喵神关于它的文章,非常及时!

remlostime commented 2 years ago

如果在state里有compute var, 如何比较 expected stateactual state呢?

remlostime commented 2 years ago

如何对BindingAction 进行 UnitTest呢?

remlostime commented 2 years ago

如何对BindingAction 进行 UnitTest呢?

store.send(.binding(.set(\.$bar, "haha"))) { state in
 ...
}

另外,bindable 应该是在0.31引入的

onevcat commented 2 years ago

Bindable 相关的应该是 0.26 就有了。测试的话,直接给 TestStore 发 .binding 的 action,应该和普通 action 没有什么不同?

remlostime commented 2 years ago

如果在state里有compute var, 如何比较 expected state 和 actual state呢?

这里似乎只能测试 expectedStatecomputeVar == expectedVal。由于 actualStateprivate的,没有办法直接测试 actualStatecomputeVar

store.send(.action) { state in
   XCTAssertEqual(state.computeVar, expectedVal)
}
onevcat commented 2 years ago

虽然确实可以在 send 的 block 里写 XCTAssertEqual,但是讲道理不是这样测的... block 里只应该给出新的 (或者修改) state,然后让 TestStore 里的断言去判断这个给出的 state 和实际的 reducer 演化出的 state 是否相等。对于 computeVar 的话,也许一个针对 State 的 unit test 就能覆盖了,并不需要 TestStore 和 action 掺合进来?


class StateTests: //... {
  func testStateComputeVar() {
    let state = State(actualVar: // ...)
    XCTAssertEqual(state.computeVar, expectedVal)
  }
}
sunyazhou13 commented 2 years ago

消化了一上午没搞懂 再继续研究一下

remlostime commented 2 years ago

另外,关于snapshotTest。最开始,store可以直接接收action,现在有viewStore了,如果要像视频里面那样直接send action,好像没法做到,在UnitTest里面有TestStore,但TestStoreSnapShot Test里面似乎不适用。那么有啥办法能一步一步的发action,然后测试snapshot image?

remlostime commented 2 years ago

Snapshot test

有个 post 也讨论了,但似乎还是不太明确

remlostime commented 2 years ago

Snapshot test updated: Here's the answer - https://forums.swift.org/t/is-it-possible-to-assert-snapshot-in-between-teststore-send-and-receive-asserts/36998/5

LRSnowX commented 2 years ago

坐等第三部分

yongyang007 commented 2 years ago

添加setCount Action并binding TextField后,在点"+"/"-"后除了原来的increment或decrement Action, debug信息显示还会收到两次setCount Action。 请问这正常么?这种情况是否应该限制setCount Action的发出?

received action:
  CounterAction.increment
  Counter(
-   count: 0,
+   count: 1,
    secret: 85
  )

received action:
  CounterAction.setCount("1")
  (No state changes)

received action:
  CounterAction.setCount("1")
  (No state changes)
wudijimao commented 2 years ago

大神们都用上了啊,我们这边已经比较激进了现在还要支持到iOS11,如果不升级到iOS 14有没有其他方案啊? 自己写一个靠不靠谱? 我看github上有https://github.com/Cosmo/OpenSwiftUI 但显然没有坚持下来

andy1413 commented 1 year ago

@onevcat 为什么对于state.count=0的测试会受secret值的影响?是否说明这个测试框架不合理呢,难道是每次创建一个新对象拿来跟原对象做对比?为什么不直接拿原对象只比较其中的某个值呢?看似Environment是为了解决这个鸡肋而产生的?

onevcat commented 1 year ago

@wangfangshuai 断言会对整个值进行比较。而且我认为这是正确的行为:随机生成的 secret 对于这个 state 来说其实是个 side effect,在测试中我们希望每次运行用例时,状态都是原子化,且是完全稳定的。Environment 的引入,可以把 side effect 完全剥离出 state,保证 reducer 是一个纯函数,这对控制复杂度和 scalable 是非常重要的。

onevcat commented 1 year ago

补充一下,其实关于测试的这个问题,有一些是否要提供 non-exhaustive 测试的讨论。其实这更多的还是涉及到究竟想要测试提供的是 TDD 的方式还是 BDD 的方式,TCA 也许会在以后给使用者更灵活的选择。

onevcat commented 1 year ago

再补充,今天发布的 0.45.0 中已经在 TestStore 中包含了exhaustivity 的设定。用户可以根据自己的需要选择是使用哪种测试方式了。