私はジェネリックスを使用してより適切に設計される可能性のあるいくつかのテストケースに取り組んでいます。 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
に拡張を行いました。
これは貢献の余地がありますか? PRを作成する前に、まずデザインを明確にしたいと思います。
これは貢献の余地がありますか? PRを作成する前に、まずデザインを明確にしたいと思います。
会話を始めて助けてくれてありがとう。 PRを作成する前にデザインも明確にしたいと思います。 = D間もなく、寄付を受け付けてしまう可能性があります。
同じ質問ですが、$#$ 1 $#$ではなくTestCaseSourceAttribute
TestCaseAttribute
の場合: 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)
Returnsメソッドに似たTestCaseData.GenericsArgs(params Type []ジェネリック)のようなメソッドを使用するのはどうですか。
それもうまくいくかもしれません。 @ nunit / framework-team、他の誰かがこのトピックを面白いと思いますか?
この問題はアイデア/デザイン/ディスカッションとしてマークされていますが、何年も貢献していないので、締めくくります。 誰かがこのアイデアに取り組むことに興味がある場合は、あなたの興味を投稿してください。チームは再開を検討します。
最も参考になるコメント
それもうまくいくかもしれません。 @ nunit / framework-team、他の誰かがこのトピックを面白いと思いますか?