web-dev-qa-db-ja.com

動的オブジェクトをNUnit TestCase関数に渡す方法は?

私はデータ集約型のアプリを書いています。次のテストがあります。それらは機能しますが、かなり冗長です。

[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);
}

異なるコンテナオブジェクトの子と同様に、最初に同じプロパティが変更され、最後にアサーションのいくつかの値が変更されます。さまざまなプロパティをチェックして、これらを数十個書く必要があります。そこで、テストをパラメーター化したいと思います。トリックは、コンテナオブジェクトをパラメータとしてテストに渡すことです。コンテナオブジェクトは、テストフィクスチャ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);
}

しかし、それは機能せず、どのように機能させるか、または可能かどうかはわかりません。

50

私はそれを追跡しました。インスタンス化されたオブジェクトをTestCaseを介してテストに渡すことはできません。これは、属性が静的なメタデータ専用であるためです。しかし、NUnitチームにはそのためのソリューション、TestCaseSourceがあります。質問に答えたNUnitリストの投稿は here です。

私のソリューションは次のようになります。

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);
}

思ったほどきれいではなく、読みやすいものでもありません。しかし、コードの重複を削減することで成功しました。これにより、保守と修正が容易になります。

114

私は時々解析する文字列を渡しますが、かなり読みやすいと思います、例:

[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());
}
6
Johan Larsson
 [Test]
    [TestCase("textbox", true, "Text is empty", null, false)]
    [TestCase("textbox", false, "Text is empty", null, true)]
    public void Test_Component_Validation_and_ValidationText__Whether_IsMandatory_IsSet(string textbox, bool isMandatory, string validationText, string value, bool expectedValue)
            {

            //Arrange
            var mockPublicPortalService = new Mock<IPublicPortalService>();
            PublicAssessmentController controller = new PublicAssessmentController(mockPublicPortalService.Object);

            // Set Component properties 
            var Component = new Component()
            {
                ComponentDatatype = textbox,
                IsMandatory = isMandatory,
                ValidationText = validationText,
                Value = value
            };

            var context = new ValidationContext(Component);

            //Act
            var results = new List<ValidationResult>();
            var isModelStateValid = Validator.TryValidateObject(Component, context, results, true);

            // Assert
            Assert.AreEqual(expectedValue, isModelStateValid);
            if (isModelStateValid == false)
            {
                Assert.IsTrue(results.Any(x => x.ErrorMessage == validationText));
            };

    }
0
Ben

これを行うプライベートメソッド、基本クラスメソッド、またはヘルパークラスを用意する方がはるかに簡単ではないでしょうか。

単体テストでは、非常にデータ集約型のアプリケーションであるため、多くのモックエンティティが必要です。初期化されたエンティティをその場で作成できる模擬リポジトリの構造を作成しました。これを組み合わせて、メモリに代表的なデータベース構造を構築できます。

そのような何かがあなたのために働く可能性があります:

// 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);
}
0