单元测试 - 不是可测试代码转换为可测试代码

ima*_*mak 4 c# unit-testing

我已经阅读了很多地方,如果你的代码不可测试,那意味着代码写得不好.这让我开始编写一个可测试的代码,并开始使用一些单元测试框架.

尽管如此,我开始寻找一些不可测试的代码并逐渐转换为可测试代码的示例.我在单元测试中找到了大量的例子,但如果有人可以提供上面的例子,它可能会为我开始.

TIA

Ste*_*ven 7

以下是两本可以帮助您入门的好书:

  1. 单元测试的艺术
  2. 有效地使用遗留代码

祝好运.

  • +1有效地使用旧版代码.塞满了很多很好的例子.必须阅读任何萌芽的TDDer. (3认同)

P.B*_*key 1

将一堆代码放入按钮单击事件中并尝试对其进行单元测试。这并非不可能,但要么是不平凡的,要么需要一些复制粘贴的花招才能完成。

protected void buttonClick(object sender, EventArgs e)
{
    string currUser =
        User.Identity.Name.ToString().Trim()
            .Substring(User.Identity.Name.ToString().Trim()
            .IndexOf("\\") + 1);

    Inventory.Employee.DB objEmpDB = new Inventory.Employee.DB();
    Inventory.Employee.Details objEmpDetails = 
        new Inventory.Employee.Details();

    objEmpDetails = objEmpDB.Get(currUser);

    Welcome.Text = 
        "Current User: " + objEmpDetails.Employee_Full_Name;

    var objUserDetails = new Inventory.User.Details();
    Inventory.User.DB objUserDB = new Inventory.User.DB();

    if (objUserDB.UserAuthenticates(currUser))
    {
        objUserDetails = objUserDB.Get(currUser);
        currUserToken = objUserDetails.User_Token.Value;

        userID.Text = currUser;

        if (objUserDetails.Active_User_Name != objUserDetails.User_Name)
        {
            lShadow.Text = "Showin: " + objUserDetails.Active_User_Name;
            lServer.Text = "(" +
            objUserDB.UserPermissionName(objUserDetails.Active_Logon_Name)
                + ") - " + System.Environment.MachineName;
            lShadow.ToolTip = Inventory.Properties.Settings.Default
                .connectionString.Substring(0, Inventory.Properties
                .Settings.Default.connectionString.IndexOf(';'));
            divShadow.Visible = true;
        }
        else
            divShadow.Visible = false;

        lWelcome.Text = "Current User: " + objUserDetails.User_Name;
    }
}
Run Code Online (Sandbox Code Playgroud)

这不仅很难,因为模拟用户按钮点击很困难,而且还要看看按钮点击中发生了多少事情。如果你的单元测试失败,大约有 100 个奇怪的地方可能出了问题。DRY、单一关注和其他设计原则使代码易于测试和修复。毕竟,如果您测试的是旅而不是单位,那么单元测试有什么好处:)

更新:(如何修复上述代码)
我不会假装上面的代码是一个简单的修复。这是我过去处理过的代码库中的一个“小”示例。我想展示现实生活中事情会变得多么糟糕。

代码有两个主要问题。

  1. 测试按钮点击事件很困难。
  2. 一种方法中发生的事情太多了。

修复事件驱动/重现按钮单击事件问题很容易。您可以将所有代码包装到另一个方法中:

protected void buttonClick(object sender, EventArgs e)
{
   EasyToCallMethod();
}

public void EasyToCallMethod()
{
    string currUser =
        User.Identity.Name.ToString().Trim()
        .Substring(User.Identity.Name.ToString().Trim().IndexOf("\\") + 1);
    //...rest of code
}
Run Code Online (Sandbox Code Playgroud)

现在可以轻松地从单元测试中调用。但是,这有点愚蠢,因为它确实没有解决第二个问题。

轻松修复
因此,我们可以通过这一方法调用进行 15-20 次良好的测试。只需对具有特定目的的每一行(例如进行方法调用的位置)进行测试,您就应该拥有良好的单元测试,这些单元测试足够小,可以告诉哪里出了问题,并且具有良好的代码覆盖率。
高级的东西
还有很多工作可以做。我们可以实现n层MVC或MVVM。在某些时候,你必须问自己是否过度设计。单元测试应该使您的代码更易于维护,但不要过度抽象成虚无。这就是你自己的风格和经验发挥作用的地方。当你觉得自己已经掌握了基础知识时,你应该带着新问题回到 SO 或拿起一本好书。