Skip to content

Instantly share code, notes, and snippets.

@sfpprxy
Last active September 18, 2020 06:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sfpprxy/1c301842cac32694546bef4c42f4f39c to your computer and use it in GitHub Desktop.
Save sfpprxy/1c301842cac32694546bef4c42f4f39c to your computer and use it in GitHub Desktop.
难以测试或测试无效化的场景

难以测试或测试无效化的场景

#buf

假设

  1. 接口是http://xxx.xxx/update_all_user, 没有其他参数
  2. 业务需求是我有一波users通过http接口取自第三方系统,想存到本项目的数据库里。根据userId这个主键来判断,如果数据库user表里有一致的主键,就把数据表这条记录中其他的字段更新成user对应的属性,否则就把user作为一条新的记录插入数据表
  3. 本项目使用了一个我不熟悉的orm库叫 internal-orm, internal-orm是我们公司自己写的内部使用的库

实操

  1. 现在internal-orm提供了3个api,分别是 writeAll() persistAll() 和 saveAll(),我不清楚这3个api的语义,我填写配置文件连接了数据库,并且尝试性的选择了writeAll来实现业务需求。
  2. 由于我不清楚 http://xxx.xxx/update_all_user 是否能像上述假设中我认为的那样工作,我想通过写测试代码来验证,由于internal-orm的api会与外部系统(数据库)交互,所以mock数据库相关对象的单元测试行不通。要测试他的正确性必须做集成测试,也就是说测试的代码也必须连接这个(或者等效的)数据库。
  3. 在不引入额外依赖的情况下,我依然使用internal-orm读取数据并验证 http://xxx.xxx/update_all_user 的正确性。
  4. internal-orm提供了 readAll 来读取数据,于是测试代码中我填写配置文件连接了数据库,并使用了 readAll 得到了一波 users ,经过代码判断对比,这波 users 的数据情况符合我的预期。我很高兴 并且认为我的接口是正确的。
  5. 系统上线运行报错:取不到某用户数据
  6. 经过人工排查,发现user表里面没有数据,原来writeAll只是把数据写到缓存里面,并没有真正落地到磁盘,同样的readAll也只是从缓存里面取出数据。persistAll 和 之前没发现的 loadAll 才是真正的会对磁盘读写的 internal-orm api

问题

  1. 一般情况下,我们认为,人是会犯错的,人为检查程序的行为也是会失误的,而且代码变更后重复的人为检查很低效。所以需要写测试代码来不断的检查 业务逻辑(或者整个程序)是否正确。(题外资讯 https://www.ruanyifeng.com/blog/2015/09/continuous-integration.html)
  2. 那么,测试代码,在某种程度上可以被看作是程序的证明,用来证明程序没有意料之外的错误。(题外资讯 https://www.zhihu.com/question/21578571/answer/700799496 ; https://zhuanlan.zhihu.com/p/36276657)
  3. 在实操中,由于测试代码的”错误”,导致了这个集成测试也没有发现项目中接口的问题。
  4. 我们发现其中导致出现问题的关键点,就是程序员这个人本身,是第一次使用或者对于库不熟悉。**那么连测试代码(及类似自动化手段)本身可能都有很大很多的问题需要人工保证,如何能够用测试代码来保证你的程序没有很大问题呢? 这个悖论的确存在吗?
  5. 如果上述悖论的确存在的话,是否可以认为:
    1. 先不管业务逻辑正确与否,抛开业务逻辑(在这个例子中,代码表达的业务逻辑本身是正确的),连集成测试级别的”自动化测试代码”也不一定能保证你的项目流畅无错的跑起来。
    2. 很多问题(比如本例、数据库配置没填对然后相关的数据库的lib又是lazy的,直到你第一次读写数据才真正建立连接,导致有时候你就算编译通过->正常启动了项目->并且调用了一些别的接口 都还没发现这个错误;等等等等其他的)的首次发现,必须依赖于人工,没有办法通过某种自动化的手段来做到,比如可能自动化手段只能发现30%的这类问题。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment