Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 如何最好地为解析器编写单元测试用例?_Unit Testing_Tdd_Testcase_Test Suite - Fatal编程技术网

Unit testing 如何最好地为解析器编写单元测试用例?

Unit testing 如何最好地为解析器编写单元测试用例?,unit-testing,tdd,testcase,test-suite,Unit Testing,Tdd,Testcase,Test Suite,我正在编写一个解析器,为每个命令生成32位操作码。例如,对于以下语句: set lcl_var = 2 我的解析器生成以下操作码: // load immdshort 2 (loads the value 2) 0x10000010 // strlocal lclvar (lcl_var is converted to an index to identify the var) 0x01000002 请注意,lcl\u var可以是任何变量,也就是说,可以给出任何变量。我如何为这个编写单元测

我正在编写一个解析器,为每个命令生成32位操作码。例如,对于以下语句:

set lcl_var = 2
我的解析器生成以下操作码:

// load immdshort 2 (loads the value 2)
0x10000010
// strlocal lclvar (lcl_var is converted to an index to identify the var)
0x01000002

请注意,
lcl\u var
可以是任何变量,也就是说,可以给出任何变量。我如何为这个编写单元测试用例?我们能避免硬编码值吗?有没有一种方法可以使其通用化?

您没有指定编写解析器所用的语言,因此为了论证起见,我假设您使用的是面向对象的语言

如果是这种情况,那么依赖注入可以帮助您解决这个问题。如果发出的操作码的目标是类的实例(例如,像File),请尝试为发射器类提供一个构造函数,该构造函数使用该类型的对象作为发出代码的目标。然后,通过单元测试,您可以传入一个模拟对象,它是目标类的子类的实例,捕获特定语句发出的操作码,并断言它们是正确的


如果您的目标类不容易扩展,您可能希望基于它创建一个接口,目标类和模拟类都可以实现。

据我所知,您应该首先为您的特定示例编写一个测试,即解析器的输入是:

set lcl_var = 2
输出为:

0x10000010 // load immdshort 2
0x01000002 // strlocal lclvar 
当您实现生产代码以通过该测试并对其进行重构后,如果您不满意,它可以处理任何局部变量,使用不同的局部变量编写另一个测试,并查看它是否通过。e、 g.具有输入的新测试:

set lcl_var2 = 2

并编写新的测试,以获得所需的不同输出。继续这样做,直到您确信您的产品代码足够健壮为止。

这取决于您如何构造解析器。单元测试测试单个单元

因此,如果您想将整个解析器作为一个单元进行测试,可以给它一个命令列表,并验证它是否生成了正确的操作码(在编写测试时手动检查)。您可以为每个命令编写测试,并测试正常使用情况、边缘情况使用情况和边缘情况使用情况。例如,测试:

设置lcl_var=2

结果:

0x1000010 0x01000002

对于0,-1,MAX_INT-1,MAX_INT+1

您知道这些值的正确结果。不同的变量也是如此。

如果您的问题是“如何使用不同的输入和期望值运行相同的测试,而不为每个输入-输出组合编写一个xUnit测试?”

int[] opcodes = Parser.GetOpcodes("set lcl_var = 2");
Assert.AreEqual(2, opcodes.Length);
Assert.AreEqual(0x10000010, opcodes[0]);
Assert.AreEqual(0x01000002, opcodes[1]);
那么答案就是使用类似RowTest NUnit的扩展。我最近在我的博客上写了一篇文章。 这方面的一个例子是

[TestFixture]
    public class TestExpression
    {
        [RowTest]
        [Row(" 2 + 3 ", "2 3 +")]
        [Row(" 2 + (30 + 50 ) ", "2 30 50 + +")]
        [Row("  ( (10+20) + 30 ) * 20-8/4 ", "10 20 + 30 + 20 * 8 4 / -")]
        [Row("0-12000-(16*4)-20", "0 12000 - 16 4 * - 20 -")]
        public void TestConvertInfixToPostfix(string sInfixExpr, string sExpectedPostfixExpr)
        {
            Expression converter = new Expression();
            List<object> postfixExpr = converter.ConvertInfixToPostfix(sInfixExpr);

            StringBuilder sb = new StringBuilder();
            foreach(object term in postfixExpr)
            {
                sb.AppendFormat("{0} ", term.ToString());
            }
            Assert.AreEqual(sExpectedPostfixExpr, sb.ToString().Trim());
        }
[TestFixture]
公共类TestExpression
{
[行测试]
[第二行(“2+3”、“2+3+”)]
[第2行(“2+(30+50)”,“23050+”]
[世界其他地区(((10+20)+30)*20-8/4”,“1020+30+20*8/-”)
[世界其他地区(“0-12000-(16*4)-20”,“0-12000-16*4*-20-”)
public void TestConvertInfextoPostFix(字符串sInfixExpr、字符串sExpectedPostfixExpr)
{
表达式转换器=新表达式();
List postfix expr=converter.ConvertInfixToPostfix(sInfixExpr);
StringBuilder sb=新的StringBuilder();
foreach(postfixExpr中的对象术语)
{
sb.AppendFormat(“{0}”,term.ToString());
}
Assert.AreEqual(sExpectedPostfixExpr,sb.ToString().Trim());
}

不清楚您是否正在寻找用于测试的方法或特定技术

就方法论而言,也许你不想做大量的单元测试。也许更好的方法是用你的领域特定语言编写一些程序,然后执行操作码来产生结果。然后测试程序会检查这个结果。这样你可以练习一堆代码,但在e从简单的开始清除明显的bug,然后转移到更难的bug,而不是每次都检查生成的操作码

另一种方法是自动生成领域特定语言的程序以及预期的操作码。这可以非常简单,就像编写一个perl脚本生成一组程序,如:

设置lcl_var=2

设置lcl_var=3

一旦您的语言中有了一套具有正确输出的测试程序,您就可以返回并生成检查每个操作码的单元测试。因为您已经有了操作码,所以检查解析器输出的正确性就成了一件事;检查其代码


虽然我没有使用cppunit,但我使用了一个非常类似于cppunit的内部工具。使用cppunit实现单元测试很容易。

您想测试什么?您想知道是否使用了正确的“存储”指令是否被创建?是否选取了正确的变量?下定决心想知道什么,测试就会很明显。只要你不知道你想实现什么,你就不知道如何测试未知

同时,只需写一个简单的测试。明天或晚些时候,你会再次来到这个地方,因为有些东西坏了。那时,你会对你想做的事情有更多的了解,设计一个测试可能会更简单


今天,不要试图成为明天的你。

我用C++硬编码编写解析器是最好的,单元测试应该非常明确地告诉你错误在代码库中的位置。如果是泛型错误,则错误可能在“有效代码列表”中,而不是在解析器中。