winforms 对Windows窗体应用程序进行单元测试的建议

h4cxqtbf  于 2023-10-23  发布在  Windows
关注(0)|答案(6)|浏览(159)

我已经写了一个Windows窗体应用程序,现在我想为它写一些单元测试(不完全是测试驱动的开发,因为我是在开发之后写测试的,但晚写总比不写好!))我的问题是,对于这样一个应用程序,如果几乎所有的方法和事件都是私有的,那么如何编写单元测试呢?我听说过NUnit表单,但我听到好的和坏的事情,也有一段时间没有真实的发展,该项目,所以它看起来被遗弃。还有,如果我为用户点击/按下按钮触发的所有事件编写单元测试用例,那么项目是否已经有了足够的单元测试,或者我是否必须为所有方法编写单元测试用例,并找出一种方法来测试我的私有方法?

**编辑:**我的业务逻辑与我的表示逻辑是分离的,我的业务逻辑公开了1到2个公共方法,因此表单可以访问它们,但是业务逻辑中的所有私有方法呢?

zvokhttg

zvokhttg1#

单元测试图形应用程序的关键是确保所有的业务逻辑都在一个单独的类中,而不是在代码后面。
Model View PresenterModel View Controller这样的设计模式可以帮助设计这样的系统。
举给予一个例子:

public partial class Form1 : Form, IMyView
{
    MyPresenter Presenter;
    public Form1()
    {
        InitializeComponent();
        Presenter = new MyPresenter(this);
    }

    public string SomeData
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            MyTextBox.Text = value;
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Presenter.ChangeData();
    }
}

public interface IMyView
{
    string SomeData { get; set; }
}

public class MyPresenter
{
    private IMyView View { get; set; }
    public MyPresenter(IMyView view)
    {
        View = view;
        View.SomeData = "test string";
    }

    public void ChangeData()
    {
        View.SomeData = "Some changed data";
    }
}

正如您所看到的,表单只有一些基础结构代码来将所有内容联系在一起。所有的逻辑都在Presenter类中,它只知道视图接口。
如果你想对它进行单元测试,你可以使用一个类似Rhino Mocks的Mocking工具来模拟View界面,并将其传递给演示者。

[TestMethod]
public void TestChangeData()
{
    IMyView view = MockRepository.DynamickMock<IMyView>();
    view.Stub(v => v.SomeData).PropertyBehavior();

    MyPresenter presenter = new MyPresenter(view);

    presenter.ChangeData();

    Assert.AreEqual("Some changed data", view.SomeData);
}
mpgws1up

mpgws1up2#

我要做的第一件事是确保您的业务逻辑与表单有适当的分离。基本上,使用MVC模式。然后,您可以轻松地测试表单之外的所有内容,就好像表单根本不存在一样。
现在,这可能仍然会留下一些未经测试的表单特定功能。即,表单是否正确连接到服务?为此,您仍然可以考虑NUnit Forms或其他替代方案。

a14dhokn

a14dhokn3#

将所有的业务逻辑分解到一个单独的项目和单元测试中,或者至少将所有逻辑从表单中移到单独的类中。

bejyjqdl

bejyjqdl4#

你有几个选择。
1.使用像Coded UI这样的工具通过用户界面进行测试。这不是一个很好的选择,因为它比单元测试慢,而且测试往往更脆弱。
1.将业务逻辑与表示逻辑分开。如果您在UI中有很多执行业务逻辑的私有方法,那么您已经将业务逻辑与表示紧密耦合。开始识别这些类,并将它们移到具有公共接口的单独类中,以便进行测试。阅读SOLID原则,它可以帮助您保持代码的松散耦合和可测试性。

dldeef67

dldeef675#

使用approvaltests(www.example.com或nuget)对View进行单元测试非常简单www.approvaltests.com。这里有一个视频:http://www.youtube.com/watch?v=hKeKBjoSfJ8
然而,您似乎也担心为了能够测试功能而将函数设置为默认或公共。
这些通常被称为接缝;进入代码进行测试的方法。而且他们很棒有时候人们会把private/public和安全性混淆起来,并且害怕把一个private函数变成public,但是反射会调用其中任何一个,所以它并不真正安全。其他时候,人们担心的是类的API接口。但只有当您有一个公共API时,这才有意义,如果您有一个winform应用程序,它可能是顶级的(没有其他消费者调用它)。
您是程序员,因此可以将代码设计为易于测试。这通常意味着只需要改变几个公共方法,并创建几个允许传入依赖项的纵容方法。
举例来说:

buttonclick += (o,e)=> {/*somecode*/};

是很难检验的

private void button1_Click(object sender, EventArgs e) {/*somecode*/}

仍然很难测试

public void button1_Click(object sender, EventArgs e) {/*somecode*/}

容易测试

private void button1_Click(object sender, EventArgs e) { DoSave();}
public void DoSave(){/*somecode*/}

真的很容易测试!
如果你需要从事件中获得一些信息,这会加倍。ie.

public void ZoomInto(int x, int y)

测试相应的鼠标单击事件要容易得多,并且passthrough调用仍然可以是一个可重写的行。

zhte4eai

zhte4eai6#

可以使用MVVM(Model-View-ViewModel)模式和Reactive.UI来编写可测试的WinForms代码。要真正做到关注点的分离。请参阅:Reactive.UI https://reactiveui.net/使用Winforms / MVVM / Reactive.UI的主要缺点是没有太多使用它的例子(对于WinForms)。好处是它适用于几乎所有的桌面框架和语言。你为一个人学习,但原则适用于所有人。当你有很多私有方法时,这是可以的。IMHO:尝试使用公共方法来开始您想要测试的业务流程。你可以使用tell-don't-ask:https://martinfowler.com/bliki/TellDontAsk.html并保持所有这些方法的私有性。
也可以通过驱动UI来测试代码,但这并不强烈推荐,因为结果测试(1)非常脆弱,(2)更难工作,恕我直言,(3)不能像纯代码测试那样以相同的精细粒度编写;(4)最后:如果你使用数据库,你将需要考虑用测试数据填充它,而且,因为你的数据库在每次测试之前必须处于干净的、定义良好的状态,(5)当你为每个测试重新初始化数据时,你的测试可能比你想象的运行得更慢。
总结:使用良好的SoC编写代码(例如:通过应用MVVM),那么你的代码将具有更好的可测试性。

相关问题