单元测试仅在调试模式下通过,在运行模式下失败

时间:2013-01-17 19:15:44

标签: visual-studio-2010 unit-testing debugging c#-4.0

我有以下UnitTest:

[TestMethod]
public void NewGamesHaveDifferentSecretCodesTothePreviousGame()
{
    var theGame = new BullsAndCows();


    List<int> firstCode = new List<int>(theGame.SecretCode);
    theGame.NewGame();
    List<int> secondCode = new List<int>(theGame.SecretCode);
    theGame.NewGame();
    List<int> thirdCode = new List<int>(theGame.SecretCode);

    CollectionAssert.AreNotEqual(firstCode, secondCode);
    CollectionAssert.AreNotEqual(secondCode, thirdCode);
}

当我在调试模式下运行它时,我的代码通过了测试,但是当我正常运行测试(运行模式)时,它没有通过。抛出的异常是:

CollectionAssert.AreNotEqual failed. (Both collection contain same elements).

这是我的代码:

// constructor
public BullsAndCows()
{
    Gueses = new List<Guess>();
    SecretCode = generateRequiredSecretCode();
    previousCodes = new Dictionary<int, List<int>>();
}

public void NewGame()
{
    var theCode = generateRequiredSecretCode();

    if (previousCodes.Count != 0)
    {
        if(!isPreviouslySeen(theCode))
        {
            SecretCode = theCode;
            previousCodes.Add(previousCodes.Last().Key + 1, SecretCode);  
        }
    }
    else
    {
        SecretCode = theCode;
        previousCodes.Add(0, theCode);
    }
 }

previousCodes 是类的属性,其数据类型是 Dictionary键整数,值整数列表 SecretCode 也是该类的属性,其数据类型是整数列表

如果我猜测,我会说原因是再次调用NewGame()方法,而第一个调用并没有真正完成它需要做的事情。如您所见,在NewGame()方法中调用了其他方法(例如generateRequiredSecretCode())。

在调试模式下运行时,按下F10的速度慢,可以为进程提供足够的时间。

但我不确定如何解决这个问题,假设我在确定原因时是正确的。

1 个答案:

答案 0 :(得分:0)

generateRequiredSecretCode生成重复时,SecretCode会发生什么?它似乎未得到处理。

一种可能性是您获得了重复,因此SecretCode保持与之前的值相同。发电机如何工作?

另外,您没有显示BullsAndCows构造函数是如何初始化SecretCode的?它在调用NewGame吗?

我怀疑按键的速度与它有什么关系,因为你的测试方法依次调用函数而不等待输入。除非generateReq...产生一个线程,否则它将在它返回之前完成它正在做的任何事情。

- 更新后 -

我看到2个错误 1)构造函数中生成的第一个SecretCode未添加到previousCodes列表中。因此,如果第二个游戏具有相同的代码,则重复检查将无法捕获 2)填充previousCodes后,您不会处理生成重复的情况。以前是重复的,因此您不会将其添加到previousCodes列表中,但也不会更新SecretCode,因此它会保留旧值。

我不确定为什么这只出现在发布模式中 - 但它可能与调试模式处理随机数生成器的方式不同。见How to randomize in WPF。释放模式更快,因此它使用与种子相同的时间戳,因此它确实生成完全相同的数字序列。

如果是这种情况,您可以通过使random成为类属性来修复它,而不是为每次调用生成器创建一个新属性。