为功能代码编写测试?
Writing tests for functional code?
举例来说,假设我们正在构建一个简单的缓存。我们可以采用闭包的函数式方法:
makeCache = ->
c = {}
(key, fetch) ->
if c[key]
c[key]
else
c[key] = fetch()
c[key]
cache = makeCache()
cache(1, -> 1)
我发现这种方法的问题是您无法轻松地对其进行测试。我希望能够检查 '1'
是否在缓存中。如果我添加更多值,我想确保它们也在缓存中。
如果我有更复杂的缓存,比如LRU缓存,我也想测试其他方面。然而,这些变量完全隐藏在闭包后面。
我倾向于使用闭包来思考解决方案,但后来我求助于面向对象的风格,以便其可测试:
class Cache
constructor: ->
@c = {}
get: (key, fetch) ->
if c[key]
c[key]
else
c[key] = fetch()
c[key]
cache = new Cache()
cache.get(1, ->1)
现在我可以访问 cache.c
以及我需要检查以进行测试的任何其他变量。
所以我的问题是,在使用函数式闭包时如何测试代码?
这不会针对您的具体情况进行测试吗?
cache = new Cache()
cache.get(1, ->1)
expect(cache.get(1, ->0)).toBe(1);
比较笼统的问题已经够真实了。但任何封装技术都是如此。不过,我会争辩说,测试或至少单元测试的整个目标是使系统的 public 接口正常工作。因此,如果您没有 public 工具来检查缓存中是否存在某些内容,那么您就不需要对其进行单元测试。
肯定有人不同意,但我觉得这是一个明确的分界线。
举例来说,假设我们正在构建一个简单的缓存。我们可以采用闭包的函数式方法:
makeCache = ->
c = {}
(key, fetch) ->
if c[key]
c[key]
else
c[key] = fetch()
c[key]
cache = makeCache()
cache(1, -> 1)
我发现这种方法的问题是您无法轻松地对其进行测试。我希望能够检查 '1'
是否在缓存中。如果我添加更多值,我想确保它们也在缓存中。
如果我有更复杂的缓存,比如LRU缓存,我也想测试其他方面。然而,这些变量完全隐藏在闭包后面。
我倾向于使用闭包来思考解决方案,但后来我求助于面向对象的风格,以便其可测试:
class Cache
constructor: ->
@c = {}
get: (key, fetch) ->
if c[key]
c[key]
else
c[key] = fetch()
c[key]
cache = new Cache()
cache.get(1, ->1)
现在我可以访问 cache.c
以及我需要检查以进行测试的任何其他变量。
所以我的问题是,在使用函数式闭包时如何测试代码?
这不会针对您的具体情况进行测试吗?
cache = new Cache()
cache.get(1, ->1)
expect(cache.get(1, ->0)).toBe(1);
比较笼统的问题已经够真实了。但任何封装技术都是如此。不过,我会争辩说,测试或至少单元测试的整个目标是使系统的 public 接口正常工作。因此,如果您没有 public 工具来检查缓存中是否存在某些内容,那么您就不需要对其进行单元测试。
肯定有人不同意,但我觉得这是一个明确的分界线。