Replies: 23 comments 85 replies
-
|
Maybe I overlooked something (I made my first TUnit steps today), but I miss a feature that you can generate the data on the specified types. Currently I am using xUnit in conjunction with AutoFixture. Basically you have to implement a Create method with all defined types as parameters. The attribute subclassing is not the perfect solution, but it does what is needed. In the end I want to write a test like this: From your documentation I can only find the MethodDataSource, but there is no way to get the information about the arguments of the test. |
Beta Was this translation helpful? Give feedback.
-
|
Hi,
Do I have the ability to repeat the test in growing intervals?
For instance, if the test fails because of a loss of connection, can I
repeat it after 10 sec min, and if still fails, then after 25 seconds,
then after 1 min?
…On Thu, Sep 26, 2024 at 7:11 PM Tom Longhurst ***@***.***> wrote:
Is there a feature that other frameworks provide that TUnit doesn't?
Is there a feature that they don't support but you wish they did?
I'm open to suggestions on anything that'd help make TUnit meet your
testing needs.
—
Reply to this email directly, view it on GitHub
<#646>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AENYVK4NKS4QI3QKYPCOLZ3ZYQ55RAVCNFSM6AAAAABO5PCE6WVHI2DSMVQWIX3LMV43ERDJONRXK43TNFXW4OZXGI2DAMZSGI>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
|
Vow! Do you have any notion of when will this come out of prerelease?Can’t wait to start using this.On 4. Oct 2024, at 00:49, Tom Longhurst ***@***.***> wrote:
Hey @MiroKov ! Yeah this can easily be done.
You can create your own retry attributes that simply inherit from RetryAttribute. Then you can plug your own logic into the ShouldRetry method.
It returns a task so you can wait asynchronously in there.
E.g.
public class ExponentialRetryAttribute(int times) : RetryAttribute(times)
{
public override async Task<bool> ShouldRetry(TestContext context, Exception exception, int currentRetryCount)
{
await Task.Delay(TimeSpan.FromSeconds(currentRetryCount));
return true;
}
}
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
|
👍On 4. Oct 2024, at 07:29, Tom Longhurst ***@***.***> wrote:
Hopefully in the next couple of months.
I'm just collecting user feedback before I mark the API as stable
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
|
Is there some way to combine multiple In my case I want to run all my tests with different with different fixtures, so I have a base class with a Here's a quick example: [TestFixtureSource(typeof(DatabaseFixtureSource))]
public abstract class WebserverTests
{
protected WebserverTests(WebserverFixture fixture)
{
Fixture = fixture;
}
protected WebserverFixture Fixture { get; }
}
public sealed class ExampleTests(WebserverFixture fixture) : WebserverTests(fixture)
{
[Test]
public void Test() => Assert.Pass();
}
[TestFixtureSource(typeof(OtherFixtureSource))]
public sealed class CombinedTests(WebserverFixture fixture, OtherFixture other) : WebserverTests(fixture)
{
[Test]
public void Test() => Assert.Pass();
}I'm not really sure what would be the best way to port this to One thing I couldn't figure out in |
Beta Was this translation helpful? Give feedback.
-
|
A feature that would be really useful would be what xUnit is calling two-phase parametrised tests. (Although it has yet to be implemented) The idea is that a data source (such as from a DataSourceGeneratorAttribute) can interrupt the enumeration of generated test cases. This is very useful for property-based testing libraries that generate multiple random test cases for a single parameterised test method. The original xUnit issue is here xunit/xunit#1719 but to paraphrase, the process is:
In the shrinking phase, the property-based testing library uses various heuristics to simplify the (randomly generated) test case to a single human-readable repro. The problem with xUnit and other existing libraries is that they see both these generated test cases and the test cases generated by the shrinking algorithm as a single test, not a parameterised one with multiple inputs, making the test runner results unhelpful. I don't think TUnit supports this yet (although if I'm wrong, I'd happily be corrected), but I'd have thought it'd be much easier to implement while the framework is still young. |
Beta Was this translation helpful? Give feedback.
-
|
It took a while for me to check back to this thread. As for the AutoFixture part, I dont think that the current implementation would fit my developers. There is no point in type checking. It just makes writing tests painful. The whole idea of writing tests with AutoFixture is that you just write parameters in your tests and they will be created behind the scenes. When I change the type of the parameter to another, then I need another parameter. This would force to change every parameter twice with no benefit. Also if you write a migration from xUnit, where you currently just subclass the AutoDataAttribute to e.g. AutoNSubstiuteDataAttribute. You would be forced to subclass every generic attribute. Writing a lot of useless code. This is done just to override the Fixture factory, so there are other ways to solve this. A matter of how much different TUnit should feel. It makes combinations also very hard to implement. Something like InlineAutoDataAttribute would need number of generic arguments minus one constructors. |
Beta Was this translation helpful? Give feedback.
-
|
I'm trying out TUnit by replacing xUnit in a small project. I'm using XUnit.Combinatorial, where the use of enums as test method parameters automatically generates a test case for each value in the enum. This is what I'm able to do with XUnit.Combinatorial: public enum MyEnum { Foo, Bar, Baz }
[Theory]
[Combinatorial]
public void MyTest(MyEnum enumValue)
{
// This generates a test for Foo, Bar, and Baz
} |
Beta Was this translation helpful? Give feedback.
-
|
With the demise of FluentAssertions, I find myself missing the CompleteWithinAsync() and NotThrowAfterAsync assertions. Is this available and/or planned ? |
Beta Was this translation helpful? Give feedback.
-
|
Hey @thomhurst! Something like this maybe where you could specify a method in the Would that be feasible and something you can imagine as a good addition? |
Beta Was this translation helpful? Give feedback.
-
|
I'd love generic type argument attributes such that I could do the following: [TypeArguments(typeof(Person), typeof(Car))]
public class MyTest<T>
{
[Test]
public async Task SomeTest()
{
// typeof(T) will be Person or Car here
}
}Or maybe even a |
Beta Was this translation helpful? Give feedback.
-
Test class with constructor parameters and non-static test data methodThis is essentially what is stated in Test class with constructor parameters and non-static test data method . While I understand the complexity of this feature, it really would be a nice thing to have. I am currently writing a small framework where I translate a C# into what is essentially a numeric-only value. This is done using source generators. In many cases I want to iterate over value inside some of these classes but also need additional test data from elsewhere: Here is an example of code that would be very nice to be able to have: [ApplicationServiceCollectionGenerator]
public class PropertyReaderTest(ApplicationServiceCollectionFixture applicationServices)
{
private readonly IEnumerable<PropertyState> _propertyStates = applicationServices.PropertyStates.Values;
private readonly IPropertyReader _propertyReader = applicationServices.PropertyReader;
private static readonly uint[] ObligatoryAttributes = new[]
{
1u, 2u, 10u, 19u, 18u
};
public IEnumerable<Func<PropertyState>> Properties()
{
return _propertyStates.Select(p => (Func<PropertyState>)(() => p));
}
[Test]
[MatrixDataSource]
public async Task CanReadProperty(
[MatrixMethod<PropertyState>(nameof(Properties))] PropertyState property,
[MatrixMethod<uint>(nameof(ObligatoryAttributes))]uint attribute)
{
var request = new ReadValueId
{
AttributeId = attribute
};
var result = _propertyReader.ReadProperty(request, property);
await Assert.That(StatusCode.IsGood(result.ResponseCode)).IsTrue();
}
}The above code, instead, generates wrongly (with value arguments (null, 0) for all combinations - any other attempt made to do something similar will not compile at all, as mentioned in the previously linked issue. The alternative to this seem to be to create a custom generator that captures both the Obligatory Attribute, the Numeric entity, and the property to read from that entity. |
Beta Was this translation helpful? Give feedback.
-
|
Would it be possible to have "pipeline style" hooks? I have been experimenting with a piece of code that will be placed within ASP.Net or NHibernate middleware and that makes use of AsyncLocal to provide some services. It seems to work great in those pipelines in that I can register the services, invoke I've been having a nightmare trying to make collections of tests using these services using NUnit because the pre-test hooks run in a different async context to the actual tests and the post-test hooks. I've already seen that I can make this work with TUnit thanks to the FlowAsyncLocals functionality (or whatever the current name is - I think when I tried this the analyser disagreed with the rest of the code on what the name of the method is). So yay, this is already a reason to want to switch. But it would be smoother if I could write And not have to manually pair up hooks (or call the async flow method). Would such a hook be feasible or is it just too alien to the way this works? |
Beta Was this translation helpful? Give feedback.
-
|
I really like the ScenarioTests extension for XUnit. It's a really interesting approach which lends itself well to tests that often require some buildup or sequence. Under the hood, it is using source generators to "multiplex" unit tests in sequence into separate tests. It reduces the sometimes tedious work of managing test state setup. |
Beta Was this translation helpful? Give feedback.
-
|
Is it possible to add a current index or parallel id for the current test context when it has a parallel limit? |
Beta Was this translation helpful? Give feedback.
-
|
After a short hiatus from TUnit, I have returned to my project. Here is the things I found confusing or annoying after getting back (still by far the best testing framework I have worked with). I want to test that my services are registered correctly and with the correct lifetimes. I created an interface to represent matchers for services descriptors, and now want to examine my IServiceCollection. I create an iterable of service descriptor matchers that I can use to check for correct registration - this is my 'expected data'. public static IEnumerable<Func<IPartialServiceMatcher>> WantedServices { get; } =
[
()=>new GenericPartialMatcher(typeof(ISimulationBuilder<,>), ServiceLifetime.Scoped),
()=>new GenericPartialMatcher(typeof(ISimulationBuilder<,,>), ServiceLifetime.Scoped),
()=>new GenericPartialMatcher(typeof(ISimulationBuilderFactory<,>), ServiceLifetime.Singleton),
()=>new GenericPartialMatcher(typeof(ISimulationBuilderFactory<,,>), ServiceLifetime.Singleton),
()=>new ConcreteServiceWithGenericImplMatcher<ISimulationStepValidator>(Implementation: typeof(Retur
()=>new GenericPartialMatcher(typeof(ISimulationExecutor<,,>), ServiceLifetime.Transient),
()=>new GenericPartialMatcher(typeof(ISimulationExecutor<,>), ServiceLifetime.Transient),
()=>new GenericPartialMatcher(typeof(ISimulationOrchestrator<,,>), ServiceLifetime.Singleton),
()=>new GenericPartialMatcher(typeof(ISimulationOrchestrator<,>), ServiceLifetime.Singleton),
()=>new GenericPartialMatcher(typeof(ISimulationProcessorPipeline<,,>), ServiceLifetime.Singleton),
()=>new GenericPartialMatcher(typeof(ISimulationProcessorPipeline<,>), ServiceLifetime.Singleton),
];I then create a single method: [Test]
[DisplayName("A service matching $matcher has been registered")]
[XXXDataSource]
public async Task ServiceIsRegistered(IPartialServiceMatcher matcher)
{
await Assert.That(_collection.Any(matcher.Equals)).IsTrue();
}but could not for the life of me figure out how to inject property data into the method. DataSourceAttribute to inject data from propertiesLooking through the types of DataSource attributes, it was not immediately obvious to me whether it is possible to use a property to inject the elements Okay, I then want to test more things - I figured it would be nice to make sure the same generic instance types has the same lifetime. So I create a test: public async Task ServicesHasWantedLifetime(IEnumerable<IPartialServiceMatcher> matchers, ServiceLifetime lifetime)
{
var wantedServices = matchers.Where(e => e.Lifetime == lifetime);
using (Assert.Multiple())
{
var provider = _collection.BuildServiceProvider();
foreach (var serviceDescriptor in wantedServices)
{
var foundService = provider.GetService(serviceDescriptor.ServiceType);
await Assert.That(foundService).IsNotNull().Because("We want to construct the service as a singleton");
}
}
}I then tried to figure out which datasource attribute I could use to inject data from WantedServices (which were refactored to a List of elements and a List<Func>) . However, I could not see a good way of combining multiple data sources. This lead me to my next wanted feature: An intuitive Api for combining data sources
|
Beta Was this translation helpful? Give feedback.
-
|
Would it be possible to add support for Junit test report format ? I think only trx is available for now. |
Beta Was this translation helpful? Give feedback.
-
|
Looking at migrating from NUnit, a few things the migration code-fixes couldn't handle: (all of which are theoretically fixable, but require rewriting every test method)
|
Beta Was this translation helpful? Give feedback.
-
|
Is it possible to have rough collection equality assertion as a first-class extension method? var target = new[] { 1, 4, 2, 5, 3 };
_ = await Assert.That(target).IsSequentiallyEqualTo([1, 4, 2, 5, 3]); |
Beta Was this translation helpful? Give feedback.
-
|
It would be nice to have an attribute that lets you override the class name which functions like [ClassName("A Tests")]
public class ClassA
{
[Test]
public async Task A1()
{
...
}
...
} |
Beta Was this translation helpful? Give feedback.
-
Custom class data source attributeI am working on a test framework design, where I can do a single assembly scanning and then find some adapter that can be used by the rest of my framework. I want to reuse the existing behaviour of Here is the example I want to have working. I made comments with what I believe I need to have working: public sealed class AdaptableFixtureAttribute<T> : DataSourceGeneratorAttribute<ISimulationFixture<T>>
{
private readonly DataSourceGeneratorAttribute<ISimulationFixture<T>> _classDataSource;
public AdaptableFixtureAttribute(
SharedType shared = SharedType.PerTestSession,
string key = FixtureKeys.ReadOnlyFixture)
{
var adapter = FrameworkAdapter.AdapterInstance;
var serverAdapter = adapter.GetSimulationServerType();
var genericType = typeof(AssemblyScanningFixture<,>).MakeGenericType(serverAdapter, typeof(T));
var innerSource = typeof(ClassDataSourceAttribute<>).MakeGenericType(genericType);
_classDataSource = (DataSourceGeneratorAttribute<ISimulationFixture<T>>)
innerSource.GetConstructor(Type.EmptyTypes)!.Invoke([]);
//here I need to be able to assign the SharedType and key to the datasource
}
protected override IEnumerable<Func<ISimulationFixture<T>>> GenerateDataSources(DataGeneratorMetadata dataGeneratorMetadata)
{
//Here I need to be able to forward the call directly to _classDataSource
//but cannot access it, since it is a protected member.
return [];
}
}The ideal usecase scenario is that I get access to the GenerateDataSources of the What are the chances of something like this being made available? What would the repercussions of gaining access to those fields? |
Beta Was this translation helpful? Give feedback.
-
|
It would be incredible if the OpenTelemetry captured when running against an Aspire Fixture was captured as part of the TUnit html report. I suspect it would be difficult to implement at the moment, given Aspire doesn't expose the OTEL traces it collects in any way. I'm following the discussion on the Aspire repo about that here: microsoft/aspire#2897. But they only seem to be work arounds at the moment. I'd be happy to contribute to this if it was possible. But I suspect having the TUnit process start a HTTP server to intercept the OTEL requests wouldn't be something you would want to add to the project - and I can't see another way to achieve it at the moment. |
Beta Was this translation helpful? Give feedback.
-
.net framework supportIt would make the move to TUnit a no-brainer if it supported .net frameowrk as well |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
-
Is there a feature that other frameworks provide that TUnit doesn't?
Is there a feature that they don't support but you wish they did?
I'm open to suggestions on anything that'd help make TUnit meet your testing needs.
Beta Was this translation helpful? Give feedback.
All reactions