【问题标题】:Unit test is acting weird - can you shed some light on this mystery?单元测试表现得很奇怪——你能解开这个谜团吗?
【发布时间】:2011-03-15 22:07:16
【问题描述】:

这是我的测试:

[TestFixture]
public class DisplayingPageLinks
{
    [Test]
    public void Can_Generate_Links_To_Other_Pages()
    {
        //Arrange: We're going to extend the Html helper class.
        //It doesn't matter if the variable we use is null            
        HtmlHelper html = null;

        PagingInfo pagingInfo = new PagingInfo(){
            CurrentPage = 2,
            TotalItems = 28,
            ItemsPerPage = 10
        };

        Func<int, String> pageUrl = i => "Page" + 1;

        //Act: Here's how it should format the links.
        MvcHtmlString result = html.PageLinks(pagingInfo, pageUrl);

        //Assert:
        result.ToString().ShouldEqual(@"<a href=""Page1"">1</a><a href=""Page2"">2</a><a href=""Page3"">3</a>");
    }
}

PageLinks 扩展方法如下:

public static MvcHtmlString PageLinks(this HtmlHelper html, PagingInfo pagingInfo, Func<int,string> pageUrl)
{
    StringBuilder result = new StringBuilder();

    for (int i = 1; i < pagingInfo.TotalPages; i++)
    {
        TagBuilder tag = new TagBuilder("a");
        tag.MergeAttribute("href", pageUrl(i));
        tag.InnerHtml = i.ToString();
        if (i == pagingInfo.CurrentPage)
        {
            tag.AddCssClass("selected");
        }
        result.Append(tag.ToString());
    }

    return MvcHtmlString.Create(result.ToString());
}

最后是运行测试的结果:

SportsStore.UnitTests.DisplayingPageLinks.Can_Generate_Links_To_Other_Pages: 预期字符串长度为 63,但为 59。 字符串在索引 24 处有所不同。
预期:“123”但是是:“12”
----------------------------------^

错误不会复制它在 GUI 中的显示方式 - 抱歉。

您能否就 NUnit 为什么说它收到我不希望它给出的东西给我一些建议。

根据我在 PageLinks 扩展方法中阅读的内容,似乎应该正确形成标记。

有什么建议吗?我是 TDD 新手,真的很想在这里学习。 :)


编辑:

看来罪魁祸首就是这个。我的测试使用的是: Func pageUrl = i => "页面" + 1;

而不是

Func pageUrl = i => "页面" + i;

但是现在出现了另一个错误。 :(

在 PagingInfo 类中计算页面数量时似乎有问题:

public class PagingInfo
{
    public int TotalItems { get; set; }
    public int ItemsPerPage { get; set; }
    public int CurrentPage { get; set; }

    public int TotalPages
    {
        get { return (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage); }
    }
}

似乎错误源于返回 2 页而不是 3 页这一事实。

这个计算有问题吗?

【问题讨论】:

    标签: c# unit-testing tdd nunit


    【解决方案1】:

    (回复您在编辑中提出的新问题。)PageLinks() 中的循环以i = 1 开头,并以i &lt; pagingInfo.TotalPages 作为条件 - 一个经典的一对一错误。 :-)

    【讨论】:

    • 就是这样! :) 有趣的是,学习新事物可以真正缩小您对某个问题的视野。感谢您的宝贵时间。
    • +1:如所写,循环只会执行 2 次。对于值 1 和 2。当 i 增加到 3 时,循环条件失败,并且第 3 次传递永远不会发生。将“(int i = 1;”更改为“(int i = 0;”)
    • @Sergio Tapia:确实——谁知道我自己多久来一次。 :-) 顺便说一句,请参阅@StriplingWarrior 的直接测试PagingInfo.TotalPages 的好建议,这将表明错误在其他地方。
    【解决方案2】:

    这个计算有问题吗?

    好问题。作为正确的测试驱动设计的练习,尝试创建一个隔离此特定计算的单元测试。像这样的:

    Assert.AreEqual(3, new PagingInfo {TotalItems = 4, ItemsPerPage = 9}.TotalPages);
    

    如果这些单元测试表明该函数正确计算了您的输入,那么您就知道消费类一定提供了错误的输入。

    这里真正的问题可能是 Aasmund 发现的问题,但我希望这个答案能让您了解如何改进单元测试以找出错误的真正来源。

    【讨论】:

    • 他已经知道当有 3 页时它会返回 2。您的测试没有显示任何内容。
    • @David B:不,他不知道——他这么认为,这是一个错误的假设。该测试(希望对各种极端情况进行更多测试)将显示PagingInfo.TotalPages 工作正常,因此问题必须在其他地方(它是,即在循环中)。所以+1这个答案。
    • @David B:他知道他得到一个包含 2 的字符串,而它应该包含 3,但他在问他的计算是否应该受到指责。像这样的测试要么表明他的计算不是罪魁祸首,他应该专注于 PageLinks 方法本身(这里就是这种情况),要么是罪魁祸首,他需要修复它。由于他说他正在尝试学习 TDD,我认为这是一个很好的机会来展示编写更有针对性的单元测试是如何有益的。
    【解决方案3】:

    这个计算有问题吗?

    public int TotalPages
    {
      get { return (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage); }
    }
    

    是的,您在所涉及的类型和操作上玩得又快又松。在不知道运算符优先级的情况下,您不知道是否在除法之前应用了小数转换,因此不知道除法是小数除法还是整数除法。

    使用多个语句并明确类型。阅读this post


    我会将反对票视为寻求更多帮助的提示。考虑一下:输入都是整数。这个问题可以在整数域中解决吗?有必要涉及小数吗?


    public int GetTotalPages()
    {
      int fullPages = TotalItems / ItemsPerPage;
      bool partialPage = TotalItems % ItemsPerPage != 0;
      int result = fullPages + (partialPage ? 1 : 0);
      return result;
    }
    

    【讨论】:

    • 虽然我不是那个投反对票的人,但我认为这是在手腕上的一记耳光,因为我会匆忙下结论。事实证明,这种方法的逻辑是正确的,而像return TotalItems / ItemsPerPage 这样的更简单的解决方案是不正确的。不幸的是,你的语气听起来很尖刻,而不是很有帮助。不过,我很想知道您将如何仅使用整数来解决此问题。
    • +1,顺便说一下,用于链接到其他 SO 帖子。非常有趣的阅读。 ( dividend + divisor - 1 ) / divisor 解决方案在这种情况下看起来效果很好,但如果看到它的人还不知道这个技巧,那么你在做什么就不太清楚了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多