Hi Remco,
I'd like to use Memberdata and see them in Test Window. Resharper displays the two scenarios just fine, but NCrunch Shows only "Kata" and from test output, it seems like it only runs BaseCasePostgres (last of the two).
Can I do anything to see the scenarios in test window?
BR, Anders
---
using Sait.VagtplanV2.Configuration;
using Sait.VagtplanV2.TestData;
using Xunit.Abstractions;
namespace Sait.VagtplanV2.Aspire.Tests;
[Collection("Integration Tests")]
public class IntegrationTestKata : IntegrationTestBase
{
public IntegrationTestKata(ITestOutputHelper output) : base(output)
{
}
[Theory]
[MemberData(nameof(ScenarioData.All), MemberType = typeof(ScenarioData))]
public void Kata(Scenario scenario)
{
var defaultCtsToken = scenario.DatabaseType == DatabaseType.Mssql ? NoTimeoutCts.Token : DefaultCts.Token;
Given(Output, DateTimeProvider, scenario.DatabaseType, defaultCtsToken)
//
.Then.TimeAdministration.Is.Healthy.And.Calculation.Is.Healthy
.With.Date20250901.As.Current.Day
//
.When.One.Duty.In.Week1.Is.Send.To.TimeAdministration
.Then.Result.Is.Success
//
.With.Date20250908.As.Current.Day
//
.When.Calculation.Of.Week1.Is.Requested
.Then.Result.Is.Success.And
.Then.Calculation.Database.For.Test.Tenant.Has.One.Calculations
//
.When.Updated.Duty.Is.Send.To.TimeAdministration
.Then.Result.Is.Success
//
.With.Date20250915.As.Current.Day
//
.When.Calculation.Of.Week2.Is.Requested
.Then.Result.Is.Success.And
.Then.Calculation.Database.For.Test.Tenant.Has.Two.Calculations
//
.Finally.Print.Summary();
}
}
public record Scenario(string Name, DatabaseType DatabaseType);
public static class ScenarioData
{
public static IEnumerable<object[]> All
{
get
{
yield return new object[]
{
new Scenario("BaseCaseMssql", DatabaseType.Mssql)
};
yield return new object[]
{
new Scenario("BaseCasePostgres", DatabaseType.Postgres)
};
}
}
}
Remco NCrunch Developer
#18491
26 Nov 2025 23:28 UTC
Hi, thanks for posting.
Xunit rolls up the cases for this test (on instruction from NCrunch) because they are built using a user-defined type declared on their signature, which introduces significant complexity and risks when transferring them from the test discovery domain into the runtime environment.
NCrunch then has an additional constraint where tests themselves can only be created during discovery, not during execution. This differs from the normal VS test adapters that can simply add dummy tests at runtime to hold the results that are discovered late in the cycle.
To avoid these test cases from being rolled up, you'll need to make sure your ScenarioData uses primitive types only (such as String or Int), since these types are very simply for the system to transfer between domains. The alternative is to specify the test statically using inlinedata instead.
You'll find that when the test cases are rolled up like they are, they'll both still be run, but the results will be reported from both cases inside the same test. This naturally means that a failure from either of them will be reported as a failure of the rolled-up test.
Xunit rolls up the cases for this test (on instruction from NCrunch) because they are built using a user-defined type declared on their signature, which introduces significant complexity and risks when transferring them from the test discovery domain into the runtime environment.
NCrunch then has an additional constraint where tests themselves can only be created during discovery, not during execution. This differs from the normal VS test adapters that can simply add dummy tests at runtime to hold the results that are discovered late in the cycle.
To avoid these test cases from being rolled up, you'll need to make sure your ScenarioData uses primitive types only (such as String or Int), since these types are very simply for the system to transfer between domains. The alternative is to specify the test statically using inlinedata instead.
You'll find that when the test cases are rolled up like they are, they'll both still be run, but the results will be reported from both cases inside the same test. This naturally means that a failure from either of them will be reported as a failure of the rolled-up test.
Edited 26 Nov 2025 23:32 UTC
I managed to solve my problem. To me the solution was to add IXunitSerializable to my Scenario -- even if it seems to make no difference whether the interface methods contain any code.
So: This works for me, displaying two test cases in Test Window.
Fun & games:
- Remove the IXunitSerializable and it doesn't work. No test cases under test.
- Remove ToString() override -- you get a very nice serialized-to-string version of Scenario, but only for first instance.
Good enough for me -- nothing you need to do on NCrunch side.
using Newtonsoft.Json;
using Xunit;
using Xunit.Abstractions;
namespace NCrunchExample;
public class Class1Tests
{
private readonly ITestOutputHelper _output;
public Class1Tests(ITestOutputHelper output)
{
_output = output;
}
[Theory]
[MemberData(nameof(All))]
public void T1(KataScenario s2)
{
_output.WriteLine(JsonConvert.SerializeObject(s2, Formatting.Indented));
}
public static IEnumerable<object[]> All()
{
yield return new object[]
{
new KataScenario("BaseCase", new DateTime(2025, 9, 1))
};
yield return new object[]
{
new KataScenario("EdgeCase", new DateTime(2025, 10, 1))
};
}
}
public class KataScenario : BaseScenario
{
public KataScenario() : base("No name")
{
}
public KataScenario(string name, DateTime dateTime) : base(name)
{
Name = name;
DateTime = dateTime;
}
public DateTime DateTime { get; }
}
public class BaseScenario : IXunitSerializable
{
public BaseScenario(string name) : this()
{
Name = name;
}
public BaseScenario()
{
}
public string Name { get; set; } = null!;
public void Deserialize(IXunitSerializationInfo info)
{
}
public void Serialize(IXunitSerializationInfo info)
{
}
public override string ToString()
{
return Name;
}
}
So: This works for me, displaying two test cases in Test Window.
Fun & games:
- Remove the IXunitSerializable and it doesn't work. No test cases under test.
- Remove ToString() override -- you get a very nice serialized-to-string version of Scenario, but only for first instance.
Good enough for me -- nothing you need to do on NCrunch side.
using Newtonsoft.Json;
using Xunit;
using Xunit.Abstractions;
namespace NCrunchExample;
public class Class1Tests
{
private readonly ITestOutputHelper _output;
public Class1Tests(ITestOutputHelper output)
{
_output = output;
}
[Theory]
[MemberData(nameof(All))]
public void T1(KataScenario s2)
{
_output.WriteLine(JsonConvert.SerializeObject(s2, Formatting.Indented));
}
public static IEnumerable<object[]> All()
{
yield return new object[]
{
new KataScenario("BaseCase", new DateTime(2025, 9, 1))
};
yield return new object[]
{
new KataScenario("EdgeCase", new DateTime(2025, 10, 1))
};
}
}
public class KataScenario : BaseScenario
{
public KataScenario() : base("No name")
{
}
public KataScenario(string name, DateTime dateTime) : base(name)
{
Name = name;
DateTime = dateTime;
}
public DateTime DateTime { get; }
}
public class BaseScenario : IXunitSerializable
{
public BaseScenario(string name) : this()
{
Name = name;
}
public BaseScenario()
{
}
public string Name { get; set; } = null!;
public void Deserialize(IXunitSerializationInfo info)
{
}
public void Serialize(IXunitSerializationInfo info)
{
}
public override string ToString()
{
return Name;
}
}
Post a reply
Log in to reply.