【问题标题】:Unit test passes when in debug but fails when run单元测试在调试时通过,但在运行时失败
【发布时间】:2011-06-19 09:59:15
【问题描述】:

搜索方法返回任何匹配的文章和最新的不匹配文章,最多指定数量。

在返回之前,匹配文章的 IsMatch 属性设置为 true,如下所示:

articles = matchingArticles.Select(c => { c.IsMatch = true; return c; }).ToList();

在测试这个方法时,

    [Test]
    public void SearchForArticle1Returns1MatchingArticleFirstInTheList()
    {
        using (var session = _sessionFactory.OpenSession())
        {
            var maxResults = 10;
            var searchPhrase = "Article1";
            IArticleRepository articleRepository = new ArticleRepository(session);
            var articles = articleRepository.GetSearchResultSet(searchPhrase, maxResults);
            Assert.AreEqual(10, articles.Count);
            Assert.AreEqual(1, articles.Where(a => a.Title.Contains(searchPhrase)).Count());
            var article = articles[0];
            Assert.IsTrue(article.Title.Contains(searchPhrase));
            Assert.IsTrue(article.IsMatch);
        }
    }

在 debug 中运行测试时所有断言都通过,但在 release 中运行测试时最终断言失败:

预期:真 但是是:错误

在应用程序本身中,响应是正确的。

关于为什么会发生这种情况的任何想法?

编辑:

我发现了问题所在。这本质上是一种竞争条件。当我设置测试时,我删除了 db 表,重新创建它并用测试数据填充它。由于搜索依赖于全文搜索,我正在相关列上创建一个文本索引并将其设置为自动填充。当它在调试中运行时,似乎有足够的时间来填充文本索引并且搜索查询返回匹配项。当我运行测试时,我认为索引没有及时填充,没有返回匹配项并且测试失败。它类似于日期时间的问题。如果我在创建目录和运行测试之间设置延迟,则测试通过。

【问题讨论】:

  • 我对count==10和count==1的检查有点糊涂,然后你随便挑文章[0]。文章顺序有多少控制权?
  • 就像@Henk Holterman 所说,您可能应该过滤到包含 searchPhrase 的位置,然后获取第一个
  • @Henk Holterman, @Oskar Kjellin 感谢收看。匹配的文章在列表中的第一位,它在存储库方法中得到处理并在其他地方进行了测试。但是,如果我按照您的建议进行操作://var article = articles[0]; var article = articles.Where(a => a.Title.Contains(searchPhrase)).ToList()[0]; Assert.IsTrue(article.Title.Contains(searchPhrase)); Assert.IsTrue(article.IsMatch); 结果是一样的。
  • @Pones 当你说when the test is run in release - 你的意思是这样还是不是在调试测试时?
  • @Oskar Kjellin,最后的断言:Assert.IsTrue(article.IsMatch); @wal,我的意思是当不调试测试时 - 只是使用 re#er 运行。

标签: c# unit-testing debugging testing


【解决方案1】:

Pones,你已经澄清了单元测试在不调试时会失败。

在这个阶段它可以是任何东西,但是你应该继续运行单元测试而不是调试,并在你知道(或认为你知道)正确的地方插入以下语句

 if(condition)
            Debugger.Launch();

这将是显而易见的,并让您能够专注于哪里出了问题。 1 我建议的地方是IsMatch 属性(对于初学者)

您可能会遇到此类问题的另一个常见地方是使用 DateTime。如果您的单元测试运行“太快”,那么它可能会打破您的假设。

【讨论】:

  • 当我按照建议运行并检查文章的 IsMatch 属性时是否为假。所以断言失败了。如果我在调试中重复 IsMatch 属性为 true。
  • 你试过Debugger.Launch( ) 不是在Debug下运行吗?
  • 是的。当我这样做时,我可以检查 IsMatch 属性,它是错误的。
  • 好的,这行之后呢? return matchingArticles.Select(c => { c.IsMatch = true; return c; }).ToList();;(在返回之前将返回值提取到一个变量中,以便您检查)
  • 我发现了问题所在。这本质上是一种竞争条件。当我设置测试时,我删除了 db 表,重新创建它并用测试数据填充它。由于搜索依赖于全文搜索,我正在相关列上创建一个文本索引并将其设置为自动填充。当它在调试中运行时,似乎有足够的时间来填充文本索引并且搜索查询返回匹配项。当我运行测试时,我认为索引没有及时填充,没有返回匹配项并且测试失败。这与日期时间问题类似。
【解决方案2】:

尝试将print outdebugnormal run 上的预期结果进行比较的实际结果

就我而言,I created entities (JBA) in the test method

debug 模式下,generated ids 分别为 1、2 和 3

但在normal running 模式下,他们知道different

这导致我的 hard-coded 值导致测试失败,所以我将它们更改为从实体获取 id 而不是硬编码的方式

希望对你有帮助

【讨论】:

    【解决方案3】:

    显然,对于其他用户,问题会有所不同,但我只是点击它,并认为我的解决方案可能会有所帮助。基本上,当您在调试模式下运行时,您只运行一个测试。当您在运行模式下运行时,除了您遇到问题的测试之外,您还运行了多个测试。

    在我的情况下,问题是那些写入全局列表的其他测试,我没有在我的测试设置中明确清除。我通过在测试开始时清除列表来解决此问题。

    我的建议是查看这是否是您面临的问题类型,即禁用所有其他测试,只“运行”您遇到问题的测试。如果它在自己运行时工作,但与其他人一起运行时不工作,你就会知道你在测试之间有一些依赖关系。

    另一个技巧是在测试中使用Console.WriteLine("test") 语句。实际上,这就是我发现我的列表中有其他测试剩余的项目的原因。

    【讨论】:

      猜你喜欢
      • 2017-10-12
      • 2022-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多