Saya sedang mengerjakan beberapa kasus uji yang mungkin dirancang lebih baik menggunakan obat generik. Saya mencoba menggunakan TestCaseSource
dengan banyak kombinasi tipe yang berbeda.
Masalah yang saya hadapi adalah penggunaan refleksi dalam pengujian saya untuk memanggil metode pengujian umum yang saya gunakan untuk validasi objek.
[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);
}
}
Namun, saya yakin desain berikut dapat menambah nilai dalam hal ini:
[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);
}
Saya telah membuat ekstensi ke TestCaseSourceAttribute
secara lokal untuk mendukung ini.
Apakah ini sesuatu yang terbuka untuk kontribusi? Saya ingin mengklarifikasi desain terlebih dahulu sebelum saya membuat PR.
Apakah ini sesuatu yang terbuka untuk kontribusi? Saya ingin mengklarifikasi desain terlebih dahulu sebelum saya membuat PR.
Terima kasih banyak telah memulai percakapan dan menawarkan bantuan. Kami ingin memperjelas desain sebelum Anda membuat PR juga. =D Kemungkinan akan segera terbuka untuk kontribusi!
Permintaan yang sama tetapi untuk TestCaseAttribute
, bukan TestCaseSourceAttribute
: https://github.com/nunit/nunit/issues/1215
Hanya kesimpulan: https://github.com/nunit/nunit/issues/150
Saya sudah harus menulis kode suboptimal hari ini, jadi saya benar-benar menginginkan ini.
Dalam konstruktor TestCaseData
, apakah menurut Anda ada cara untuk membedakan nilai Type
secara lebih visual yang mengisi parameter metode generik dari nilai Type
yang mengisi parameter metode biasa?
Untuk dapat ditemukan: bagaimana dengan new TestCaseData<T1, T2>(ordinaryArg1, ordinaryArg2)?
Atau ini, yang memungkinkan kita untuk menghindari mendeklarasikan N kelas TestCaseData
baru:
TestCaseData.Create<T1, T2>(ordinaryArg1, ordinaryArg2, ordinaryArg3)
Bagaimana dengan menggunakan metode seperti TestCaseData.GenericsArgs(params Type[] generics) yang mirip dengan metode Pengembalian.
Itu bisa berhasil juga. @nunit/framework-team, ada yang menganggap topik ini menarik?
Masalah ini ditandai sebagai ide/desain/diskusi tetapi tidak memiliki kontribusi selama bertahun-tahun, jadi saya tutup. Jika ada yang tertarik untuk mengerjakan ide ini, kirimkan minat Anda dan tim akan mempertimbangkan untuk membuka kembali.
Komentar yang paling membantu
Itu bisa berhasil juga. @nunit/framework-team, ada yang menganggap topik ini menarik?