Nunit: TestCaseSourceAttribute рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░реЗрдВ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 15 рдирд╡ре░ 2017  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: nunit/nunit

рдореИрдВ рдХреБрдЫ рдкрд░реАрдХреНрд╖рдг рдорд╛рдорд▓реЛрдВ рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдЬреЗрдирд░рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмреЗрд╣рддрд░ рддрд░реАрдХреЗ рд╕реЗ рдбрд┐рдЬрд╛рдЗрди рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдореИрдВ рдХрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрдпреЛрдЬрдиреЛрдВ рдХреЗ рд╕рд╛рде TestCaseSource рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рдЬрд┐рд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдореИрдВ рд╕рд╛рдордирд╛ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рд╡рд╣ рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдзрд┐ рдХрд╛ рдЖрд╣реНрд╡рд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдореИрдВ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП рдХрд░рддрд╛ рд╣реВрдВред

[TestFixture]
public class SomeTests
{
    public static IEnumerable<TestCaseData> TestCases()
    {
        yield return
            new TestCaseData(
                typeof(Foo),
                typeof(Bar),
                Generator.Foo,
                Assertions.Foo);
        yield return
            new TestCaseData(
                typeof(Bar),
                typeof(Foo),
                Generator.Bar,
                Assertions.Bar);
    }

    [TestCaseSource(nameof(TestCases))]
    public void CheckSomeTypes(
        Type sourceType,
        Type destinationType,
        TSource source,
        Action<object, object> assert)
    {
        GetType()
            .GetMethod(nameof(CheckSomeTypesImpl), BindingFlags.Public | BindingFlags.Instance)
            .MakeGenericType(new[] { sourceType, destinationType })
            .Invoke(this, new object[] { source, assert });
    }

    public void CheckSomeTypesImpl<TSource, TDestination>(
        TSource source,
        Action<TSource, TDestination> assert)
    {
        var destination = Mapper.Map<TSource, TDestination>(source);

        // Assert are equiviliant
        assert(source, destination);
    }
}

рд╣рд╛рд▓рд╛рдБрдХрд┐, рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛтАЛтАЛрд╣реИ рдХрд┐ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдбрд┐рдЬрд╝рд╛рдЗрди рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдореВрд▓реНрдп рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ:

[TestFixture]
public class SomeTests
{
    public static IEnumerable<TestCaseData> TestCases()
    {
        yield return
            new TestCaseData(
                typeof(Foo),
                typeof(Bar),
                Generator.Foo,
                Assertions.Foo);
        yield return
            new TestCaseData(
                typeof(Bar),
                typeof(Foo),
                Generator.Bar,
                Assertions.Bar);
    }

    [TestCaseSource(nameof(TestCases))]
    public void CheckSomeTypes<TSource, TDestination>(
        TSource source,
        Action<TSource, TDestination> assert)
    {
        var destination = Mapper.Map<TSource, TDestination>(source);

        // Assert are equiviliant
        assert(source, destination);
    }
}

public class Foo
{
    public string Qux { get; set; }
}

public class Bar
{
    public string Qux { get; set; }
}

public static class Generator
{
    public static Foo Foo =>
        new Foo { Qux = "TestTestTest" };
    public static Bar Bar =>
        new Foo { Bar = "AnotherAnotherAnother" };
}

public static class Mapper
{
    // Generic mapper function
    public static TDestination Map<TSource, TDestination>(TSource source)
    {
        if (typeof(TSource) == typeof(Foo))
        {
            return Map((Foo) source);
        }

        if (typeof(TSource) == typeof(Bar))
        {
            return Map((Bar) source);
        }

        throw new NotImplementedException($"No mapping for {typeof(TSource).FullName}.");
    }

    public static Foo Map(Bar bar)
    {
        return new Foo { Qux = bar.Qux };
    }

    public static Bar Map(Foo foo)
    {
        return new Bar { Qux = foo.Qux };
    }
}

public static class Assertions
{
    public static Action<Foo, Bar> Foo =>
        (foo, bar) => Assert.AreEqual(foo.Qux, bar.Qux);
    public static Action<Bar, Foo> Bar =>
        (bar, foo) => Assert.AreEqual(bar.Qux, foo.Qux);
}

рдореИрдВрдиреЗ рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдерд╛рдиреАрдп рд╕реНрддрд░ рдкрд░ TestCaseSourceAttribute рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд┐рдпрд╛ рд╣реИред

рдХреНрдпрд╛ рдпрд╣ рдпреЛрдЧрджрд╛рди рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЦреБрд▓рд╛ рд╣реИ? рдкреАрдЖрд░ рдмрдирд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдореИрдВ рдбрд┐рдЬрд╛рдЗрди рдХреЛ рд╕реНрдкрд╖реНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдпрд╣ рднреА рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИред @ рдиреВрдирд┐рдЯ/рдлреНрд░реЗрдорд╡рд░реНрдХ-рдЯреАрдо, рдХрд┐рд╕реА рдФрд░ рдХреЛ рдпрд╣ рд╡рд┐рд╖рдп рджрд┐рд▓рдЪрд╕реНрдк рд▓рдЧрддрд╛ рд╣реИ?

рд╕рднреА 4 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдХреНрдпрд╛ рдпрд╣ рдпреЛрдЧрджрд╛рди рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЦреБрд▓рд╛ рд╣реИ? рдкреАрдЖрд░ рдмрдирд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдореИрдВ рдбрд┐рдЬрд╛рдЗрди рдХреЛ рд╕реНрдкрд╖реНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рдмрд╛рддрдЪреАрдд рд╢реБрд░реВ рдХрд░рдиреЗ рдФрд░ рдорджрдж рдХреА рдкреЗрд╢рдХрд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХрд╛ рдмрд╣реБрдд-рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рджред рдЖрдкрдХреЗ рдкреАрдЖрд░ рдмрдирд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╣рдо рдбрд┐рдЬрд╝рд╛рдЗрди рдХреЛ рд╕реНрдкрд╖реНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред =D рдпрд╣ рдЬрд▓реНрдж рд╣реА рдпреЛрдЧрджрд╛рди рдХреЗ рд▓рд┐рдП рдЦреБрд▓рд╛ рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ!

рд╡рд╣реА рдкреВрдЫреЗрдВ рд▓реЗрдХрд┐рди TestCaseAttribute рдХреЗ рд▓рд┐рдП, TestCaseSourceAttribute рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ: https://github.com/nunit/nunit/issues/1215
рдХреЗрд╡рд▓ рдЕрдиреБрдорд╛рди: https://github.com/nunit/nunit/issues/150

рдореБрдЭреЗ рдЖрдЬ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрдк-рдЗрд╖реНрдЯрддрдо рдХреЛрдб рд▓рд┐рдЦрдирд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рдЪрд╛рд╣рд┐рдПред

TestCaseData рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ, рдХреНрдпрд╛ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ Type рдорд╛рдиреЛрдВ рдХреЛ рдФрд░ рдЕрдзрд┐рдХ рдиреЗрддреНрд░рд╣реАрди рд░реВрдк рд╕реЗ рдЕрд▓рдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИ рдЬреЛ рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдзрд┐ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рднрд░рдиреЗ рд╡рд╛рд▓реЗ Type рдорд╛рдиреЛрдВ рд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдзрд┐ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рднрд░рддреЗ рд╣реИрдВ?

рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП: new TestCaseData<T1, T2>(ordinaryArg1, ordinaryArg2)? . рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛

рдпрд╛ рдпрд╣, рдЬреЛ рд╣рдореЗрдВ N рдирдИ TestCaseData рдХрдХреНрд╖рд╛рдПрдВ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рд╕реЗ рдмрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛:
TestCaseData.Create<T1, T2>(ordinaryArg1, ordinaryArg2, ordinaryArg3)

рд░рд┐рдЯрд░реНрди рд╡рд┐рдзрд┐ рдХреЗ рд╕рдорд╛рди TestCaseData.GenericsArgs(params Type[] Generic) рдЬреИрд╕реА рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ред

рдпрд╣ рднреА рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИред @ рдиреВрдирд┐рдЯ/рдлреНрд░реЗрдорд╡рд░реНрдХ-рдЯреАрдо, рдХрд┐рд╕реА рдФрд░ рдХреЛ рдпрд╣ рд╡рд┐рд╖рдп рджрд┐рд▓рдЪрд╕реНрдк рд▓рдЧрддрд╛ рд╣реИ?

рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдПрдХ рд╡рд┐рдЪрд╛рд░/рдбрд┐рдЬрд╝рд╛рдЗрди/рдЪрд░реНрдЪрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд░реНрд╖реЛрдВ рдореЗрдВ рдпреЛрдЧрджрд╛рди рдирд╣реАрдВ рд╣реБрдЖ рд╣реИ рдЗрд╕рд▓рд┐рдП рдореИрдВ рдмрдВрдж рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдЕрдЧрд░ рдХрд┐рд╕реА рдХреЛ рдЗрд╕ рд╡рд┐рдЪрд╛рд░ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реИ, рддреЛ рдЕрдкрдиреА рд░реБрдЪрд┐ рдкреЛрд╕реНрдЯ рдХрд░реЗрдВ рдФрд░ рдЯреАрдо рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдЧреАред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

yaakov-h picture yaakov-h  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

GitSIPA picture GitSIPA  ┬╖  5рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

TobiasSekan picture TobiasSekan  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

zastrowm picture zastrowm  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Prodigio picture Prodigio  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ