Debugging Erlang—自动向代码中添加调试/跟踪语句

Debugging Erlang—自动向代码中添加调试/跟踪语句,debugging,erlang,trace,Debugging,Erlang,Trace,问题:许多带有套件的Erlang模块需要每天运行,以检查是否引入了新的bug。对于那些引入bug的情况,我们希望在测试用例失败之前找到确切的位置以及可能的程序状态。由于时间限制,无法使用dbg或其他调试工具进行调试。通常测试套件包含一些打印语句,这些语句允许以某种方式精确定位bug的位置,但它们的频率太低,无法发挥作用。通常,调试语句是手动添加的,但这需要时间 建议的解决方案: 我想获取给定测试用例或整个公共测试套件的代码,并为每行测试代码创建至少一个带有行号和行内容的打印输出。例如,代码:

问题:许多带有套件的Erlang模块需要每天运行,以检查是否引入了新的bug。对于那些引入bug的情况,我们希望在测试用例失败之前找到确切的位置以及可能的程序状态。由于时间限制,无法使用dbg或其他调试工具进行调试。通常测试套件包含一些打印语句,这些语句允许以某种方式精确定位bug的位置,但它们的频率太低,无法发挥作用。通常,调试语句是手动添加的,但这需要时间

建议的解决方案: 我想获取给定测试用例或整个公共测试套件的代码,并为每行测试代码创建至少一个带有行号和行内容的打印输出。例如,代码:

       L = [spawn(mod, loop, [0]) || _ <- lists:seq(1,10)],
       [H|T] = L,
       PidList = T ++ [self()],

L=[spawn(mod,loop,[0])| | | |你也有eunit测试吗?也许eunit是实现你想要的更好的工具?通常,通过单元测试,你试图用特定的输入和预期的输出来限制特定的情况,eunit测试比较宏会精确地转储出哪个表达式上的哪个测试和行不符合预期,等等,因此你可以立即进行测试如果你知道失败的是什么,并假设它是一个没有副作用的测试,你可能确切地知道什么是失败的,并且可以立即复制它。这是个好主意,但不可行-测试不是单元测试,而且重写它们会花费太多的时间。单元测试和系统测试确实有完全不同的目的,不要把你的系统测试重写为非单元测试it测试,只需随着时间的推移开始添加单元测试。在某个时候,它会带来回报。您不需要一直运行所有启用跟踪的测试套件。希望您的测试失败是可重复的,在这种情况下,当测试失败时(只有在那时)您是否在启用跟踪或其他检测的情况下重新运行该测试用例以了解更多信息。我同意,我不想一直运行所有跟踪的整个套件。当测试用例反复失败时,我需要为这些情况生成跟踪代码,我们需要找出它失败的确切位置。您是否也有eunit测试?也许eunit是一个更好的测试工具实现所需的ool?通常,在单元测试中,您尝试使用特定的输入和预期的输出来绑定特定的情况,而eunit测试比较宏将准确地转储哪个表达式上的哪个测试和行不符合预期,等等,因此您立即知道失败的是什么,并假设它是一个无副作用的测试你可能确切地知道什么是被破坏的,并且可以立即复制它。这是个好主意,但不可行-测试不是单元测试,而且重写它们会花费太多时间。单元测试和系统测试的目的真的很不同,不要将系统测试重写为单元测试,只要随着时间的推移开始添加单元测试。在某个时候,这将带来好处。您不需要一直运行所有启用跟踪的测试套件。希望您的测试失败是可重复的,在这种情况下,当测试失败时(并且只有在那时)您是否在启用跟踪或其他检测的情况下重新运行该测试用例以了解更多信息。我同意,我不想一直运行所有跟踪的整个套件。当测试用例反复失败时,我需要为这些用例生成跟踪代码,我们需要找出它失败的确切位置。
 io:format("Line ~p : ~p",[LineNumber1, LineContent1]),
 L = [spawn(mod, loop, [0]) || _ <- lists:seq(1,10)],
 io:format("Line ~p : ~p",[LineNumber2, LineContent2]),
 [H|T] = L,
 io:format("Line ~p : ~p",[LineNumber3, LineContent3]),
 PidList = T ++ [self()],