如何将dynamic对象传递给NUnit TestCase函数?
我正在编写一个数据密集型应用程序。 我有以下testing。 他们工作,但他们是相当多余的。
[Test] public void DoSanityCheck_WithCountEqualsZeroAndHouseGrossIsGreater_InMerchantAggregateTotals_SetsWarning() { report.Merchants[5461324658456716].AggregateTotals.ItemCount = 0; report.Merchants[5461324658456716].AggregateTotals._volume = 0; report.Merchants[5461324658456716].AggregateTotals._houseGross = 1; report.DoSanityCheck(); Assert.IsTrue(report.FishyFlag); Assert.That(report.DataWarnings.Where(x=> x is Reports.WarningObjects.ImbalancedVariables && x.mid == 5461324658456716 && x.lineitem == "AggregateTotals").Count() > 0); } [Test] public void DoSanityCheck_WithCountEqualsZeroAndHouseGrossIsGreater_InAggregateTotals_SetsWarning() { report.AggregateTotals.ItemCount = 0; report.AggregateTotals._volume = 0; report.AggregateTotals._houseGross = 1; report.DoSanityCheck(); Assert.IsTrue(report.FishyFlag); Assert.That(report.DataWarnings.Where(x=> x is Reports.WarningObjects.ImbalancedVariables && x.mid == null && x.lineitem == "AggregateTotals").Count() > 0); } [Test] public void DoSanityCheck_WithCountEqualsZeroAndHouseGrossIsGreater_InAggregateTotalsLineItem_SetsWarning() { report.AggregateTotals.LineItem["WirelessPerItem"].ItemCount = 0; report.AggregateTotals.LineItem["WirelessPerItem"]._volume = 0; report.AggregateTotals.LineItem["WirelessPerItem"]._houseGross = 1; report.DoSanityCheck(); Assert.IsTrue(report.FishyFlag); Assert.That(report.DataWarnings.Where(x=> x is Reports.WarningObjects.ImbalancedVariables && x.mid == null && x.lineitem == "WirelessPerItem").Count() > 0); }
相同的属性在开始时被修改,就像不同容器对象的子对象一样,并且断言中的一对值在最后改变。 我需要写几十个,检查不同的属性。 所以我想参数化testing。 诀窍是将容器对象作为parameter passing给testing。 容器对象在testing夹具SetUp中被实例化。
我想实现的是这样的:
[TestCase(report.AggregateTotals.LineItem["WirelessPerItem"], 0, "WirelessPerItem")] [TestCase(report.AggregateTotals, 4268435971532164, "AggregateTotals")] [TestCase(report.Merchants[5461324658456716].AggregateTotals, 5461324658456716, "WirelessPerItem")] [TestCase(report.Merchants[4268435971532164].LineItem["EBTPerItem"], 4268435971532164, "EBTPerItem")] public void DoSanityCheck_WithCountEqualsZeroAndHouseGrossIsGreater_TestCase_SetsWarning(object container, long mid, string field) { container.ItemCount = 0; container._volume = 0; container._houseGross = 1; report.DoSanityCheck(); Assert.IsTrue(report.FishyFlag); Assert.That(report.DataWarnings.Where(x=> x is Reports.WarningObjects.ImbalancedVariables && x.mid == mid && x.lineitem == field).Count() > 0); }
但是这不起作用,我不确定如何使其工作,或者如果可能的话。
我追查下来 我不能通过TestCase将实例化的对象传递到testing中,因为属性是严格用于静态元数据的。 但NUnit团队为此提供了一个解决scheme,即TestCaseSource。 NUnit列表上回答问题的post就在这里 。
以下是我的解决scheme现在的样子:
public IEnumerable<TestCaseData> CountEqualsZeroAndHouseGrossIsGreaterTestCases { get { Setup(); yield return new TestCaseData(report, report.Merchants[4268435971532164].LineItem["EBTPerItem"], 4268435971532164, "EBTPerItem").SetName("ReportMerchantsLineItem"); yield return new TestCaseData(report, report.Merchants[5461324658456716].AggregateTotals, 5461324658456716, "WirelessPerItem").SetName("ReportMerchantsAggregateTotals"); yield return new TestCaseData(report, report.AggregateTotals, null, "AggregateTotals").SetName("ReportAggregateTotals"); yield return new TestCaseData(report, report.AggregateTotals.LineItem["WirelessPerItem"], null, "WirelessPerItem").SetName("ReportAggregateTotalsLineItem"); } } [TestCaseSource("CountEqualsZeroAndHouseGrossIsGreaterTestCases")] public void DoSanityCheck_WithCountEqualsZeroAndHouseGrossIsGreater_TestCase_SetsWarning(Reports.ResidualsReport report, Reports.LineItemObject container, long? mid, string field) { container.ItemCount = 0; container._volume = 0; container._houseGross = 1; report.DoSanityCheck(); Assert.IsTrue(report.FishyFlag); Assert.That(report.DataWarnings.Where(x=> x is Reports.WarningObjects.ImbalancedVariables && x.mid == mid && x.lineitem == field).Count() > 0); }
不如我所希望的那么美,不容易阅读。 但它确实成功地减less了代码重复,这使得维护和修复更容易。
我传递了我有时候parsing的string,认为它读得很好,例如:
[TestCase("15°", "-10°", 25, typeof(Degrees))] [TestCase("-10°", "15°", -25, typeof(Degrees))] [TestCase("-10°", "0°", -10, typeof(Degrees))] [TestCase("-90°", "1.5707 rad", -3.1414, typeof(Radians))] [TestCase("1.5707 rad", "-90°", 3.1414, typeof(Radians))] [TestCase("1.5707 rad", "1.5707 rad", 0, typeof(Radians))] public void SubtractionTest(string lvs, string rvs, double ev, Type et) { var lv = Angle.Parse(lvs); var rv = Angle.Parse(rvs); var diff = lv - rv; Assert.AreEqual(ev, diff.Value, 1e-3); Assert.AreEqual(et, diff.Unit.GetType()); }
有一个私人的方法,基类方法或助手类为你做这个不是很容易吗?
对于我的unit testing,我需要许多模拟实体,因为它是一个非常密集的应用程序。 我创build了一个模拟存储库的结构,可以在运行中创build初始化实体,我可以将它们结合起来,在内存中构build一个具有代表性的数据库结构。
像这样的东西可以为你工作:
// Wild guess at the class name, but you get the idea private void InitializeTotals(AggregateItem item) { item.ItemCount = 0; item._volume = 0; item._houseGross = 1; } [Test] public void DoSanityCheck_WithCountEqualsZeroAndHouseGrossIsGreater_InMerchantAggregateTotals_SetsWarning() { InitializeTotals(report.Merchants[5461324658456716].AggregateTotals); report.DoSanityCheck(); Assert.IsTrue(report.FishyFlag); Assert.That(report.DataWarnings.Where(x => x is Reports.WarningObjects.ImbalancedVariables && x.mid == 5461324658456716 && x.lineitem == "AggregateTotals").Count() > 0); } [Test] public void DoSanityCheck_WithCountEqualsZeroAndHouseGrossIsGreater_InAggregateTotals_SetsWarning() { InitializeTotals(report.AggregateTotals); report.DoSanityCheck(); Assert.IsTrue(report.FishyFlag); Assert.That(report.DataWarnings.Where(x => x is Reports.WarningObjects.ImbalancedVariables && x.mid == null && x.lineitem == "AggregateTotals").Count() > 0); } [Test] public void DoSanityCheck_WithCountEqualsZeroAndHouseGrossIsGreater_InAggregateTotalsLineItem_SetsWarning() { InitializeTotals(report.AggregateTotals.LineItem["WirelessPerItem"]); report.DoSanityCheck(); Assert.IsTrue(report.FishyFlag); Assert.That(report.DataWarnings.Where(x => x is Reports.WarningObjects.ImbalancedVariables && x.mid == null && x.lineitem == "WirelessPerItem").Count() > 0); }