Ich habe viel Zeit damit verbracht, dieses Projekt in meinem Projekt herauszufinden. This related Github discussion von @NPadrutt selbst hat sehr geholfen, aber es war immer noch verwirrend.
Die tl; dr, ist dies: [MemberInfo]
wird einen einzigen Gruppentest berichten, es sei denn die zur Verfügung gestellten Objekte für jeden Test vollständig serialisiert und deserialisiert von IXunitSerializable
Umsetzung sein können.
Hintergrund
Mein eigener Testaufbau war so etwas wie:
public static IEnumerable<object[]> GetClients()
{
yield return new object[] { new Impl.Client("clientType1") };
yield return new object[] { new Impl.Client("clientType2") };
}
[Theory]
[MemberData(nameof(GetClients))]
public void ClientTheory(Impl.Client testClient)
{
// ... test here
}
Der Test zweimal lief, einmal für jedes Objekt aus [MemberData]
, wie erwartet. Wie @NPadrutt erfahren hat, wurde nur ein Element im Test-Explorer statt zwei angezeigt. Dies liegt daran, dass das angegebene Objekt Impl.Client
nicht von beiden Schnittstellen serialisiert werden konnte (mehr dazu später).
In meinem Fall wollte ich Testbelange nicht in meinen Hauptcode bluten. Ich dachte, ich könnte einen dünnen Proxy um meine wahre Klasse schreiben, der den xUnit-Runner glauben lässt, er könnte ihn serialisieren, aber nachdem ich länger damit gekämpft hatte, als ich zugeben wollte, wurde mir klar, dass ich den Teil nicht verstand :
Die Objekte werden nicht nur während der Erkennung serialisiert, um Permutationen zu zählen; Jedes Objekt ist auch deserialized zur Testlaufzeit, während der Test beginnt.
Daher muss jedes Objekt, das Sie mit [MemberData]
bereitstellen, eine vollständige Round-Trip (De-) Serialisierung unterstützen. Das scheint mir jetzt offensichtlich, aber ich konnte keine Dokumentation darüber finden, während ich versuchte, es herauszufinden.
Lösung
Stellen Sie sicher, jedes Objekt (und jede nicht-primitive es enthalten kann) kann vollständig serialisiert und deserialisiert werden. Die Implementierung von xUnit IXunitSerializable
teilt xUnit mit, dass es ein serialisierbares Objekt ist. Wenn Sie, wie in meinem Fall, dem Hauptcode keine Attribute hinzufügen möchten, besteht eine Lösung darin, eine dünne serialisierbare Builder-Klasse zum Testen zu erstellen, die alles darstellen kann, was zum Erstellen der tatsächlichen Klasse benötigt wird.Hier ist der obige Code, nachdem ich es an die Arbeit:
TestClientBuilder
public class TestClientBuilder : IXunitSerializable
{
private string type;
// required for deserializer
public TestClientBuilder()
{
}
public TestClientBuilder(string type)
{
this.type = type;
}
public Impl.Client Build()
{
return new Impl.Client(type);
}
public void Deserialize(IXunitSerializationInfo info)
{
type = info.GetValue<string>("type");
}
public void Serialize(IXunitSerializationInfo info)
{
info.AddValue("type", type, typeof(string));
}
public override string ToString()
{
return $"Type = {type}";
}
}
-Test
public static IEnumerable<object[]> GetClients()
{
yield return new object[] { new TestClientBuilder("clientType1") };
yield return new object[] { new TestClientBuilder("clientType2") };
}
[Theory]
[MemberData(nameof(GetClients))]
private void ClientTheory(TestClientBuilder clientBuilder)
{
var client = clientBuilder.Build();
// ... test here
}
Es ist leicht ärgerlich, dass ich nicht bekommen, das Ziel Objekt wird nicht mehr injiziert, aber es ist nur eine zusätzliche Codezeile, um meinen Builder aufzurufen. Und meine Tests gehen vorbei (und erscheinen zweimal!), Also beschwere ich mich nicht.
IIRC finden gibt es ein Github Problem abdeckt diese und/oder dort behandelt wurde –
Du dich daran erinnern, die Ausgabe von war? Ich konnte kein Problem finden, das dies beschreibt. – NPadrutt
Sorry konnte nichts finden, was eindeutig passt. Vielleicht hilft Ihnen das Lesen von [this one] (https://github.com/xunit/xunit/issues/7), zu verbalisieren, wonach Sie auf GitHub suchen (z. B. Entdeckung, Vorauflistung von Theorien, Test) Methode vs Testfall). Ich würde auch in die Dokumente schauen, um zu bestimmen, was das beabsichtigte Verhalten für v2 und für v1 backcompat ist (dh das Vorauflisten von Theorien ist ein zweischneidiges Schwert, wenn man Ressourcen pro Testfall hoch/runter drehen muss) –