WPF验证输入(即时)和单元测试。设计的最佳实践

时间:2014-04-23 13:10:18

标签: c# wpf validation testing

我想在现有解决方案中添加新表单。该解决方案已经有一个Validator类,所以我想扩展这个类。

我想要创建的表单包含一个文本框(用于输入)和一个Button。当输入格式正确时,将启用提交按钮。输入必须遵循某个正则表达式:“^ [A-Za-z] {2} [0-9] {5} $”。我正在检查Form类中的输入(on-the-fly),如下所示:

private void inputTbx_TextChanged(object sender, TextChangedEventArgs e)
{
    SubmitButton.IsEnabled = Validator.IsInputValid(inputTbx.Text, RegexExpression);
}

我将正则表达式作为Form类中的变量。我把它放在这里是因为它只与这个表格的文本框相关。

private const string RegexExpression = "^[A-Za-z]{2}[0-9]{5}$"; 

这是验证码:

public static bool IsInputValid(string inputToBeChecked, string regexExpression)
{
    if (inputToBeChecked == null || regexExpression == null)
    {
        return false;
    }
    var regex = new Regex(regexExpression, RegexOptions.None);
    return regex.IsMatch(inputToBeChecked);
}

到目前为止一切顺利。它似乎工作正常。但是我想对它进行单元测试:

[TestCase("aZ13579")]
public void ValidateInputOkTest(string input)
{
    Assert.IsTrue(Validator.IsInputValid(input, RegexExpression));
}

但要像这样做,我必须在ValidatorTest类中有一个字符串,类似于Form类中使用的Regular-expression。这似乎不是正确的方法。我真正想做的是从表单类中获取Regex表达式,因此我确信它是我正在使用的正确的Regex表达式。否则,Regex表达式很容易失去同步。

以下是问题: 这里的最佳做法是什么? 我如何得到这个表达式?我尝试过使用Reflection,但是我得到一个Threadstat错误,因为它是一个GUI组件。我应该移动正则表达式吗?如果是这样的话? 我认为必须有一个聪明的方法来做到这一点。也许一个聪明的设计。欢迎提出建议和意见。

1 个答案:

答案 0 :(得分:0)

您可能想要备份一步并开始研究'MVVM'设计模式。当你听到人们谈论在代码中没有代码时,这样的测试是其中一个很大的好处(在许多其他代码中)。

在这样一个简单的答案中,MVVM太大了。我会在网上搜索,我相信其他人都有一些很好的教程。

为了清楚起见,它可能是一个很大的学习曲线,但它是完全值得的。 MVVM使WPF比WinForms更好(多),而不仅仅是不同。

为了更具体地解决您的问题,您将不会测试像Window或UserControl这样的GUI对象。您将测试一个只是常规类的视图模型。

以下是您可能会看到的简化版本

public class MyScreenViewModel : INotifyPropertyChanged
{
  private const string RegexExpression = "^[A-Za-z]{2}[0-9]{5}$"; 

  public bool UserInputIsValid { get { stuff; } set { stuff; }}
  public string UserInput { get { stuff; } set { stuff; ValidateUserInput();} }

  private void ValidateUserInput()
  {
    if (UserInput == null)
    {
        return false;
    }
    var regex = new Regex(RegexExpression, RegexOptions.None);
    UserInputIsValid = regex.IsMatch(UserInput);
  }
}

MVVM中的视图模型是屏幕的真实逻辑。它将公开视图可以绑定到显示/输入的简单属性,但视图不是测试逻辑所必需的。

然后你的测试看起来像:

[TestCase("aZ13579")]
public void ValidateInputOkTest()
{
  var vm = new MyScreenViewModel();
  vm.UserInput = "SomeValidText";

  Assert.IsTrue(vm.UserInputIsValid);
}

[TestCase("aZ13580")]
public void ValidateInputNotOkTest()
{
  var vm = new MyScreenViewModel();
  vm.UserInput = "SomeInvalidText";

  Assert.IsFalse(vm.UserInputIsValid);
}