有关测试与生产的不同数据/ priv的任何最佳实践吗?

时间:2014-11-23 16:01:01

标签: erlang rebar eunit

我正在用EUnit编写测试,一些被测单元需要通过文件读取数据文件:consult / 1 。我的测试假设了 / priv 中可用的数据,但生产中的数据会有所不同。实现这一目标的最佳方法是什么?

我是Erlang的新手,我想到了一些对我来说有点难看的解决方案。例如,

  • 将两个文件放在 / priv 中并使用宏(例如“-ifdef(EUNIT)”)来确定要传递给文件的文件:consult / 1 。这似乎太脆弱/容易出错。
  • 让Rebar将正确的文件复制到 / priv

另外,请随意指出我是否正在尝试做一些根本错误的事情。情况可能就是这样。

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

我认为你的两个解决方案都能奏效。这是维护此类测试的问题,而且这两个测试都依赖于一些外部设置(文件存在,并且具有正确的数据)。

对我来说,最简单的方法是将此类文件的内容保存在给定测试的本地,这样就可以模拟,并使file:consult/1返回您想要的值。

7> meck:new(file, [unstick, passthrough]).
ok
8> meck:expect(file, consult, fun( _File ) -> {some, data} end).
ok
9> file:consult(any_file_at_all).
{some,data}

它会起作用,但还有两件事你可以做。

首先,您根本不应该测试file:consult/1。它是标准库的一部分,并且可以假设它可以全部工作。您应该测试使用从此文件中读取的数据的函数,而不是这样做;当然还会向他们传递一些“测试中创建的”数据。它将为您提供数据源之间的良好分离,以及解析(处理)它。以后,通过调用外部服务或类似的东西来替换file:consult可能更简单。

其他问题是测试某些东西的问题应该是你的难闻气味的迹象。您可能会考虑重新设计系统。我不是说你必须这样做,但这些问题是很好的指标。如果您测试某些功能x,并且您希望它在生产和其他测试中表现一种方式(读取一个文件或另一个文件),那么应该将这种行为注入其中。或者换句话说,也许你应该读取的函数应该是这个函数中的参数。如果您希望在生产代码中仍然有一些“默认文件读取”功能,您可以使用类似的东西

function_with_file_consult(A, B, C) ->
   function_with_file_consult(A, B, C, "default_file.dat").


function_with_file_consult(A, B, C, File) ->
   [ ... actual function logic  ...  ] 

它允许您在生产中使用更短的版本,并且仅在您的测试中使用更长的版本。