c#xunit经常农行网银k宝监测不到到是怎么回事

您所在的位置: &
1.5.1 使用xUnit做单元测试
1.5.1 使用xUnit做单元测试
人民邮电出版社
《测试驱动开发的艺术》第1章综述,本章介绍了在给客户交付支持组织经营运作的软件过程中遇到的问题和挑战。传统的软件开发方法在这些方面尚有相当大的改进余地:制造出的软件缺陷率高,不容易修改,修改成本高,且不能满足客户的真正需要。本节为大家介绍使用xUnit做单元测试。
1.5 TDD工具
工具十分重要。想象一下若没有编译器、编辑器以及操作系统,软件开发将会多么困难。经过数十年的技术进步,软件开发工作已经大大简化了。我们在使用TDD开发程序时也一样,好的工具能使情况大为改观。下面我们将会简要介绍三种主要的工具和技术:单元测试框架、持续集成及其实现工具以及代码覆盖率。
1.5.1 使用xUnit做单元测试
Kent Beck在很多年以前用SmallTalk语言编写了一个叫做SUnit()的单元测试框架。这个框架在软件开发社区内掀起了一阵狂潮,随后几乎所有语言都有了自己的移植版本 。对Java开发者来说,JUnit是标准的单元测试工具,它也是由SUnit移植而来(可以在下载)。所有这些参照SUnit或JUnit而设计的单元测试框架都相似,因此被统称为xUnit。只要掌握其中一种,其他的也就不难学习了(只要你熟悉对应的编程语言就行)。
xUnit中所定义的单元测试框架到底是何概念?单元测试框架是指能够辅助单元测试编写、测试以及报告的框架。例如JUnit提供了许多基类供开发人员扩展,还提供了一些比较执行结果的类和接口,等等。框架还会提供不同的测试执行器(test runner)来运行单元测试。这个类会收集所有测试类,执行之,然后收集测试结果,最后用文本或者图形的形式将测试结果展现给开发人员。
本书中我们将会使用JUnit及Java,实际上还会用到许多JUnit的扩展,以测试驱动不同的组件。如果你还不熟悉JUnit,参阅附录中有关这个工具的简介。不过现在不要花太多时间研究JUnit,我们还会介绍许多工具,例如支持ATDD的工具等。
【责任编辑: TEL:(010)】&&&&&&
关于&&&&的更多文章
本书采用故事模式讲述一门编程语言,以一个无知的菜鸟成长过程为
本书描述了黑客用默默无闻的行动为数字世界照亮了一条道路的故事。
如何应对21世纪新商业环境中的变化?全球最大商务社交
这本书是写给程序员和项目经理的。作者结合自身的丰富
本书全面讲解WPF的实际工作原理,是一本WPF权威著作。
本书从基础知识入手,详细讨论了Oracle数据库的创建、OEM及iSQL*Plus等工具的使用、Oracle的字符集知识、用户的创建与管理、表空
51CTO旗下网站C#版本的xUnit的测试框架模型和xUnit.NET开源项目 - Wolf Li - 推酷
C#版本的xUnit的测试框架模型和xUnit.NET开源项目 - Wolf Li
1. 参考kent beck的测试驱动写的C#测试框架模型
&&&&a) 测试用例: WasRun, 基类为TestCase
&&& b) 框架: TestCaseTest用来测试TestCase,本身也是它的子类,可使用run调用自己的方法
&&& c)重点:为WasRun和TestCase,添加setUp,tearDown功能
&&&&d)然后,TestResult用来返回和传递结果,主要是计数的结果
&&&& e) 最后,TestSuite封装一组测试,并在TestCaseTest中测试
&&&&&&WasRun&=&TestCase&=&TestSuite&=&TestCaseTest&=& Main
2.另外开源完整的测试框架可参考这里
贴上模型的代码,大家自己按类区分吧。
namespace xUnit
&&& class Program
&&&&&&& static void Main(string[] args)
&&&&&&&&&&& //(new TestCaseTest(&testTemplateMethod&)).run();
&&&&&&&&&&& //(new TestCaseTest(&testTemplateMethod&)).run();
&&&&&&&&&&& //(new TestCaseTest(&testResult&)).run();
&&&&&&&&&&& //(new TestCaseTest(&testFailedResultFormatting&)).run();
&&&&&&&&&&& //(new TestCaseTest(&testFailedResult&)).run();
&&&&&&&&&&& (new TestCaseTest(&testSuite&)).run(new TestResult());
&&&&&&&&&&& Console.ReadLine();
namespace xUnit
&&& class TestResult
&&&&&&& private int runC
&&&&&&& private int errorC
&&&&&&& public TestResult()
&&&&&&&&&&& runCount = 0;
&&&&&&&&&&& errorCount = 0;
&&&&&&& public string summary()
&&&&&&&&&&& string sumStr = && + runCount + & run, & + errorCount + & failed&;
&&&&&&&&&&& return sumS
&&&&&&& public void testStarted()
&&&&&&&&&&& runCount++;
&&&&&&& public void testFailed()
&&&&&&&&&&& errorCount++;
using System.Collections.G
using System.L
using System.T
using NUnit.F
namespace xUnit
&&& class TestCaseTest : TestCase
&&&&&&& public TestCaseTest(string p) : base(p)
&&&&&&&&&&& // TODO: Complete member initialization
&&&&&&&&&&& this.p =
&&&&&& //private WasR
&&&&&&& TestR
&&&&&&& public override void setUp()
&&&&&&&&&&& //test = new WasRun(&testMethod&);
&&&&&&&&&&& result = new TestResult();
&&&&&&& public void testTemplateMethod()
&&&&&&&&&&& WasRun test = new WasRun(&testMethod&);
&&&&&&&&&&& test.run(result);
&&&&&&&&&&&
&&&&&&&&&&& try
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Assert.AreEqual(&setUp testMethod tearDown &, test.log);
&&&&&&&&&&& }
&&&&&&&&&&& catch (Exception ex)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Console.WriteLine(ex.Message);
&&&&&&&&&&& }
&&&&&&& public void testResult()
&&&&&&&&&&& WasRun test = new WasRun(&testMethod&);
&&&&&&&&&&& test.run(result);
&&&&&&&&&&& try
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Assert.AreEqual(&1 run, 0 failed&, result.summary());
&&&&&&&&&&& }
&&&&&&&&&&& catch (Exception ex)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Console.WriteLine(ex.Message);
&&&&&&&&&&& }
&&&&&&& public void testFailedResult()
&&&&&&&&&&& WasRun testFailed = new WasRun(&testBrokenMethod&);
&&&&&&&&&&& testFailed.run(result);
&&&&&&&&&&& try
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Assert.AreEqual(&1 run, 1 failed&, result.summary());
&&&&&&&&&&& }
&&&&&&&&&&& catch (Exception ex)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Console.WriteLine(ex.Message);
&&&&&&&&&&& }
&&&&&&& public void testFailedResultFormatting()
&&&&&&&&&&& result.testStarted();
&&&&&&&&&&& result.testFailed();
&&&&&&&&&&& try
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Assert.AreEqual(&1 run, 1 failed&, result.summary());
&&&&&&&&&&& }
&&&&&&&&&&& catch (Exception ex)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Console.WriteLine(ex.Message);
&&&&&&&&&&& }
&&&&&&& public void testSuite()
&&&&&&&&&&& TestSuite suite = new TestSuite();
&&&&&&&&&&& suite.add(new WasRun(&testMethod&));
&&&&&&&&&&& suite.add(new WasRun(&testBrokenMethod&));
&&&&&&&&&&& suite.run(result);
&&&&&&&&&&& try
&&&&&&&&&&& {
&&&&&&&&&&&&&&& string msg = result.summary();
&&&&&&&&&&&&&&& Console.WriteLine(msg);
&&&&&&&&&&&&&&& Assert.AreEqual(&2 run, 1 failed&, msg);
&&&&&&&&&&& }
&&&&&&&&&&& catch (Exception ex)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Console.WriteLine(ex.Message);
&&&&&&&&&&& }
using System.C
using System.Collections.G
using System.L
using System.T
namespace xUnit
&&& class TestSuite
&&&&&&& ArrayL
&&&&&&& public TestSuite()
&&&&&&&&&&& tests = new ArrayList();
&&&&&&& public void add(WasRun test)
&&&&&&&&&&& tests.Add(test);
&&&&&&& public void run(TestResult result)
&&&&&&&&&&& foreach (WasRun test in tests)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& test.run(result);
&&&&&&&&&&& }
using System.Collections.G
using System.L
using System.R
using System.T
namespace xUnit
&&& class TestCase
&&&&&&& protected string methodName = &&;
&&&&&&& public TestCase()
&&&&&&& public TestCase(string methodName)
&&&&&&&&&&& this.methodName = methodN
&&&&&&& public void run(TestResult result)
&&&&&&&&&&& result.testStarted();
&&&&&&&&&&& setUp();
&&&&&&&&&&& try
&&&&&&&&&&& {
&&&&&&&&&&&&&&& Type t = this.GetType();
&&&&&&&&&&&&&&& MethodInfo method = t.GetMethod(methodName);
&&&&&&&&&&&&&&& method.Invoke(this, null);
&&&&&&&&&&& }
&&&&&&&&&&& catch (Exception e)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& result.testFailed();
&&&&&&&&&&&&&&& Console.WriteLine(&运行测试程序设定抛出的异常,& + e.InnerException.Message);
&&&&&&&&&&& }
&&&&&&&&&&
&&&&&&&&&&& tearDown();
&&&&&&& public virtual void setUp()
&&&&&&& public virtual void tearDown()
using System.Collections.G
using System.L
using System.T
namespace xUnit
&&& class WasRun : TestCase
&&&&&&& public string log = &&;
&&&&&&& public WasRun(string p)
&&&&&&&&&&& : base(p)
&&&&&&&&&&& // TODO: Complete member initialization
&&&&&&&&&&& this.p =
&&&&&&& public void testMethod()
&&&&&&&&&&& //wasRun =
&&&&&&&&&&& log += &testMethod &;
&&&&&&& public void testBrokenMethod()
&&&&&&&&&&& throw new Exception(&testBrokenMethod test failed&);
&&&&&&& public override void setUp()
&&&&&&&&&&& //wasRun =
&&&&&&&&&&& //wasSetUp =
&&&&&&&&&&& log += &setUp &;
&&&&&&& public override void tearDown()
&&&&&&&&&&& log += &tearDown &;
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致今天看啥 热点:
此文收集一些平时使用单元测试碰到的问题和解决办法,供大家参考。 如何检查返回的集合类是否符合期望?
Microsoft UnitTestFramework 如果需要元素的顺序一致,可以使用CollectionAssert.AreEqual;如果不需要考虑顺序,可以使用CollectionAssert.AreEquivalent。(有的地方说MSTest的Assert.AreEqual支持集合类型比较,我测试过,忽悠人的)
nUnit 同上
xUnit xUnit的Assert.Equal(c1, c2)可以支持集合类型比较,c1和c2的元素顺序必须一致 Microsoft UnitTestFramework / nUnit / xUnit 比较,使用哪个框架更合适? Microsoft UnitTestFramework和nUnit的用法非常类似,而xUnit由于吸取了nUnit的设计上的经验,用法更加简洁。下面是周公写的两篇文章,nUnit和xUnit介绍的非常详细,大家可以阅读一下:
在.NET开发中的单元测试工具之(1)——NUnit
在.NET开发中的单元测试工具之(2)——xUnit.Net 什么是Mock? 单元测试的目标是一次只验证一个方法,小步的前进,细粒度的测试,但是假如某个方法依赖于其他一些难以操控的东东,比如说网络连接、数据库连接、系统时间、或者是Servlet容器,那么我们该怎么办呢?要是你的测试依赖于系统的其他部分,甚至是系统的多个其他部分呢?在这种情况下,倘若不小心,你最终可能会发现自己几乎初始化了系统的每个组件,而这只是为了给一个测试创造足够的运行环境让它们可以运行起来。忙乎了大半天,看上去我们好像有点违背了测试的初衷了。这样不仅仅消耗时间,还给测试过程引入了大量的耦合因素,比如说,可能有人兴致冲冲地改变了一个接口或者数据库的一张表,突然,你那卑微的单元测试的神秘的挂掉了。在这种情况发生几次之后,即使是最有耐心的开发者也会泄气,甚至最终放弃所有的测试,那样的话后果就不能想像了。 再让我们看一个更加具体的情况:在实际的面向对象软件设计中,我们经常会碰到这样的情况,我们在对现实对象进行构建之后,对象之间是通过一系列的接口来实现。这在面向对象设计里是最自然不过的事情了,但是随着软件测试需求的发展,这会产生一些小问题。举个例子,用户A现在拿到一个用户B提供的接口,他根据这个接口实现了自己的需求,但是用户A编译自己的代码后,想简单模拟测试一下,怎么办呢?这点也是很现实的一个问题。我们是否可以针对这个接口来简单实现一个代理类,来测试模拟,期望代码生成自己的结果呢?幸运的是,有一种测试模式可以帮助我们:mock对象。Mock对象也就是真实对象在调试期的替代品。 什么时候需要使用Mock? 关于什么时候需要Mock对象,Tim Mackinnon给我们了一些建议:
真实对象具有不可确定的行为(产生不可预测的结果,如股票的行情)
真实对象很难被创建(比如具体的web容器)
真实对象的某些行为很难触发(比如网络错误)
真实情况令程序的运行速度很慢
真实对象有用户界面
测试需要询问真实对象它是如何被调用的(比如测试可能需要验证某个回调函数是否被调用了)
真实对象实际上并不存在(当需要和其他开发小组,或者新的硬件系统打交道的时候,这是一个普遍的问题) 如何使用Mock? .NET Mock Framework有哪些,可以看看下面几个网页:
.NET Mocking Framework对比
What C# mocking framework to use? The Fakes Framework in Visual Studio 2012 关于Mock框架的实现方式,大概有两种:基于动态代理实现;基于编译时静态织入实现。各个框架的用法看一下介绍很快就可以掌握了,关键是如何使用各种mock技术,存在的争论主要有下面几个:
像Typemock、Moles、The Fakes Framework这类静态织入技术的框架,可以支持对Sealed Class、Non-Abstract Method、Non-Virtual Method、Static Method的Mock。有些人觉得这很强大,有些人觉得这反倒不好,他们认为像Moq、Rhino Mocks这类的框架,正因为不支持前面说的四类情况的mock,强迫项目必须实现依赖倒置,从而降低了项目的耦合性,以达到较高的可测试性以及可维护性。 在使用动态代理方式的Mock框架时候,为了“可测试性”,protected方法必须是virtual的,因为我们需要在子类中进行override。同理,Mock框架能够辅助的方法也必须是virtual的,即使是一个public方法。那么,您觉得这是为了可测试性而做出的让步吗?或者换句话说,您觉得,一个不可以override的protected方法,但是会影响到其他公开接口的功能,这是不是一个合理的设计呢?如果这是一个合理的设计,又不想作出这样的让步……我们又该怎么做呢?(这段话摘自老赵的“与protected成员有关的单元测试方式”) 在使用动态代理方式的Mock框架时候,为了测试一些Non-Abstract Method、Non-Virtual Method、Static Method,提供一个被测方法/类的Wrapper,封装对无法直接访问方法的调用,是否合适?做法参考:http://blog.zhaojie.me/2009/08/unit-test-protected-method.html#comment_iX2whQ8q04I003i2http://blog.zhaojie.me/2009/08/unit-test-protected-method.html#comment_iX2whQ8q04I003hi
使用Mono.Cecil解决无法Mock非虚方法和密闭类的问题
protected成员有关的单元测试方式
如何 Mock 非虚方法和密封类? 了解何时使用 Override 和 New 关键字(C# 编程指南) C# 类教程-多态性
相关搜索:
相关阅读:
相关频道:
&&&&&&&&&&&&&&&&
C#教程最近更新  关于《》系列文章,我想跟大家分享的不是简单的运行一下测试用例或是介绍一下标签怎么使用(这样的文章网上很多)。上一篇《》介绍xUnit.Net的一些基本概念。从这一篇开始我将会为大家逐一展示xUnit.Net的强大之处。还是先看一下本文要讨论的内容:
xUnit.Net 单元测试用例的类型
简单测试用例 & Fact 标签
数据驱动的用例 & Theory 标签
(一)xUnit.Net 单元测试用例的类型
  这里我先回顾一下前一篇文章的测试用例:
2 using System.Collections.G
5 public class EqualExample
public void EqualStringIgnoreCase()
string expected = "TestString";
string actual = "teststring";
Assert.False(actual == expected);
Assert.NotEqual(expected, actual);
Assert.Equal(expected, actual, StringComparer.CurrentCultureIgnoreCase);
  你可能已经发现,xUnit.Net的中用来标记测试方法的attribute是[Fact],而不是一个像类似[Test]这样更传统的标记名称。xUnit.Net 包含了两种主要的单元测试方式:Fact 和 Theory,这两种方式的不同如下:
Fact:表示测试结果永远成立的那些Unit Test,他们的输入条件不变。
Theory:表示测试是针对某一组数据的(即需要数据驱动的Unit Test&data-driven test&)。
(二)简单的测试用例 & Fact 标签
  首先,我们来看一下Fact标签的结构:
// Summary:
Attribute that is applied to a method to indicate that it is a fact that
should be run by the test runner. It can also be extended to support a customized
definition of a test method.
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
[XunitTestCaseDiscoverer("Xunit.Sdk.FactDiscoverer", "xunit.execution.{Platform}")]
public class FactAttribute : Attribute
public FactAttribute();
// Summary:
Gets the name of the test to be used when the test is skipped. Defaults to
null, which will cause the fully qualified test name to be used.
public virtual string DisplayName { get; set; }
// Summary:
Marks the test so that it will not be run, and gets or sets the skip reason
public virtual string Skip { get; set; }
  除了构造函数之外,该Attribute还提供了两个属性。
DisplayName : 用来设置Test Case 显示名称(如果是自定义的Runner,也可以通过该属性获取Test Case的名称)。
Skip:如果设置了该属性,相当于Ignore了对应的测试用例,该用例将不会被运行。
[Fact(DisplayName = "Lesson02.Demo01")]
public void Demo01_Fact_Test()
int num01 = 1;
int num02 = 2;
Assert.Equal&int&(3, num01 + num02);
[Fact(DisplayName = "Lesson02.Demo02", Skip = "Just test skip!")]
public void Demo02_Fact_Test()
int num01 = 1;
int num02 = 2;
Assert.Equal&int&(3, num01 + num02);
  对于上面的两个测试用例,运行结果如下。可以看到两个测试用例的名称均显示为DisplayName对用的属性名称,而设置了Skip属性的Unit Test没有被执行。
(三)数据驱动的用例 & Theory 标签
  关于数据驱动的测试方法,我想计算机专业出身的小伙伴应该不会陌生。这里我希望读者对等价类、边界值、错误推测、因果图,判定表驱动,正交试验设计... ...这些概念有一定的了解(知道是什么就行)。简单来说,数据驱动的测试指的是我们的测试输入和测试结果有着一定的关系,不同的输入可能会导致输出结果的不同。例如:测试登录方法,不同的用户名\密码输入后,会显示不一样的错误信息。这里,我不想过多的讨论数据驱动的测试方法应该如何设计相关的测试用例。本文的目的只要是向大家展示xUnit.Net对数据驱动的支持。
  xUnit.Net对数据驱动测试方法的支持是通过Theory attribute实现的。你可以用Theory替代Fact来标记你的测试方法,于此同时使用[XXXData]来提供你的输入和输出数据。目前[XXXData] attribute包括[InlineData]和[MemberData]。下面我们会介绍这些 attribute的使用。
@Theory简介
  查看Theory的源码可以看到,Theory是继承自Fact的。因此,之前提到的DisplayName和Skip也同样适用于Theory。
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
[XunitTestCaseDiscoverer("Xunit.Sdk.TheoryDiscoverer", "xunit.execution.{Platform}")]
public class TheoryAttribute : FactAttribute
public TheoryAttribute();
@InlineData
  Theory 和 InlineData 提供了一种简单的数据驱动方式,代码如下:
[Theory(DisplayName = "Lesson02.Demo03")]
[InlineData(1, 1, 2)]
[InlineData(1, 2, 3)]
[InlineData(2, 2, 4)]
public void Demo03_Theory_Test(int num01, int num02, int result)
Assert.Equal&int&(result, num01 + num02);
  InlineData标签的构造函数接受一个params object[] data类型的参数,值得注意的是InlineData参数的类型和数量应当与测试方法完全匹配。在Test Explorer视图中我们可以看到,该方法相当于三个测试用例,这很好的提高了测试用例的复用率和可维护性:
@MemberData
  InlineData已经为我们提供了基本的数据驱动测试的能力,但同时也有几个问题:
当测试样本很多时(尤其是在划分出的等价类数量很多,或是想做大样本测试的情况下),就会导致测试用了的InlineData变得非常长。
测试数据是从外部导入(例如:Excel,数据库,文本文件... ...),而不是硬编码。
  面对上述的情况的时候,我们就需要使用MemberData来完成工作。顾名思义,MemberData使用了一个当前类的某个成员来完成数据测试数据的注入,也就是用你可以使用当前测试类的方法,属性,字段进行数据的注入。是不是感觉棒棒哒~~。首先,我们来看一下MemberData的定义:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
[CLSCompliant(false)]
[DataDiscoverer("Xunit.Sdk.MemberDataDiscoverer", "xunit.core")]
public sealed class MemberDataAttribute : MemberDataAttributeBase
public MemberDataAttribute(string memberName, params object[] parameters);
protected override object[] ConvertDataItem(MethodInfo testMethod, object item);
  [MemberData]构造函数接受两个参数:第一,成员名称(即方法,属性或字段的名称)。第二,一个参数列表(只针对方法)。例外,需要注意以下两点:
为MemberData提供数据源的方法,属性或字段都必须是静态的。
成员返回的测试数据类型应该是IEnumerable&object[]&。
下面我们来看几个具体的例子:
示例一:MemberData & 属性
  下面的Code中定义了属性 InputData_Property,并在测试方法上用MemberData标记说明数据源来自对应的属性。
#region MemberData InputData_Property
public static IEnumerable&object[]& InputData_Property
var driverData = new List&object[]&();
driverData.Add(new object[] { 1, 1, 2 });
driverData.Add(new object[] { 1, 2, 3 });
driverData.Add(new object[] { 2, 3, 5 });
driverData.Add(new object[] { 3, 4, 7 });
driverData.Add(new object[] { 4, 5, 9 });
driverData.Add(new object[] { 5, 6, 11 });
return driverD
[Theory(DisplayName = "Lesson02.Demo04")]
[MemberData("InputData_Property")]
public void Demo04_Theory_Test(int num01, int num02, int result)
Assert.Equal&int&(result, num01 + num02);
#endregion
  在Test Explorer可以看到对应的测试用例有6组:
示例二:MemberData & 方法
  下面的Code中定义了属性InputData_Method,细心的同学会发现提供数据源的方法中多了一个flag参数。这个参数的值从何而来呢?就是我们之前说的MemberData属性的第二个构造参数(下面代码的21行)。
#region MemberData InputData_Method
public static IEnumerable&object[]& InputData_Method(string flag)
var driverData = new List&object[]&();
if (flag == "Default")
driverData.Add(new object[] { 1, 1, 2 });
driverData.Add(new object[] { 1, 2, 3 });
driverData.Add(new object[] { 2, 3, 5 });
driverData.Add(new object[] { 3, 4, 7 });
driverData.Add(new object[] { 4, 5, 9 });
driverData.Add(new object[] { 5, 6, 11 });
return driverD
[Theory(DisplayName = "Lesson02.Demo05")]
[MemberData("InputData_Method", "Default")]
//[MemberData("InputData_Method", "Other")]
public void Demo05_Theory_Test(int num01, int num02, int result)
Assert.Equal&int&(result, num01 + num02);
#endregion MemberData InputData_Method
  此时,我们在Test Exporer视图中只能看见三个测试用例,如图所示。这里xUnit.Net为我们提供了根据不同的需要加载不同数据源的可能。例如:例子中的flag参数可以是一个Excel文件名称,参数不同即可读取不同的文件。这里我就不展开讨论了,后续的文章会专门讨论这个问题。
示例三:MemberData & 字段
  其实,用属性和方法作为数据源,已经可以解决很多问题了。最后,我们来看一下如何使用字段作为数据源实现数据驱动的测试。
  首先,我们定义一个新的类型:
public class MatrixTheoryData&T1, T2& : TheoryData&T1, T2&
public MatrixTheoryData(IEnumerable&T1& data1, IEnumerable&T2& data2)
Contract.Assert(data1 != null && data1.Any());
Contract.Assert(data2 != null && data2.Any());
foreach (T1 t1 in data1)
foreach (T2 t2 in data2)
Add(t1, t2);
  这里用到了TheoryData类,这个类是有xUnit.Net提供。其中T1,T2表示了输入数据的类型。也就是说这种方式是一种类型安全的输入方式(其实,xUnit还提供了1至5个参数的TheoryData泛型)。这里使用输入的两个数据集合做笛卡尔积的结果,来充当数据源。下面看一下使用的代码:
#region MemberData InputData_Field
public static int[] Numbers = { 5, 6, 7 };
public static string[] Strings = { "Hello", "world!" };
public static MatrixTheoryData&string, int& MatrixData = new MatrixTheoryData&string, int&(Strings, Numbers);
[Theory(DisplayName = "Lesson02.Demo06")]
[MemberData("MatrixData")]
public void Demo06_Theory_Test(string x, int y)
Assert.Equal(y, x.Length);
#endregion MemberData InputData_Field
  MatrixData字段在构造的时候就会按照规则(使用Numbers,Strings的笛卡尔积)构造对应的数据源。看一下Test Explorer视图,此方法对应了6(3&2 = 6)个用例,用例的参数就是两个数组的笛卡尔积的组合:
  本文主要介绍了xUnit.Net的基本使用和针对数据驱动测试的支持。主要包含以下几点:
xUnit.Net基本使用:Fact简介。
数据驱动测试基本概念。
xUnit.Net 针对数据驱动测试的支持。
描述了以属性,方法,字段作为数据源的异同。
小北De系列文章:
  《[小北De编程手记]:C# 进化史》(未完成)
  《》(未完成)
Demo地址:/DemoCnblogs/xUnit.Net
如果您认为这篇文章还不错或者有所收获,可以点击右下角的【推荐】按钮,因为你的支持是我继续写作,分享的最大动力!
作者:小北@North
来源:/NorthAlan
声明:本博客原创文字只代表本人工作中在某一时间内总结的观点或结论,与本人所在单位没有直接利益关系。非商业,未授权,贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。
阅读(...) 评论()

我要回帖

更多关于 农行网银k宝监测不到 的文章

 

随机推荐