Migration from XUnit is painful.
Design which requires assert to be awaitable, make migration from XUnit or MSUnit or NUnit painful.
-
All tests now have to be
async Taskwhich is.. you know... lot of typing. -
That looks super strange to compare things in awaitable fashion.
Assert.Equal(new char[] { 'D' }, input.ВисокошвидкосніПрінтери);
vs
await Assert.That(new char[] { 'D' }).IsEqualTo(input.ВисокошвидкосніПрінтери);
- Same problem but with untyped new.
Assert.Equal(new("PRODUCT-NO", 'A'), input.Перший);
Assert.Equal(new("PRODUCT-NO", 'B'), input.Другий);
become
await Assert.That(new ПосиланняНаПоле("PRODUCT-NO", 'A')).IsEqualTo(input.Перший);
await Assert.That(new ПосиланняНаПоле("PRODUCT-NO", 'B')).IsEqualTo(input.Другий);
notice that I have to write type name.
- Other small details, is that you cannot use collection initializers in your asserts, thus require rewriting tests again.
Probably only XUnit related.
var input = Assert.IsType<Input>(операція);
become
await Assert.That(операція).IsTypeOf(typeof(Input));
var input = (Input)операція;
- Cannot compare
TandT?for simple types.
Assert.Equal((ushort)10, input.Більше);
become
await Assert.That((ushort?)10).IsEqualTo(input.Більше);
- Ooh. I just notice. You insist on having specific order of declaration
await Assert.That('A').IsEqualTo(input.ІсходнийФайл);
is invalid, since I have to rewrite like that.
await Assert.That(input.ІсходнийФайл).IsEqualTo('A');
which is understandable, but again. I have to retype a lot of code.
- I don't know what's going on, but when comparing arrays I cannot use
IsEqualsToand have to useIsEquivalentTowhich is not what I expect from other frameworks. - When I try to compare array of tuples, it does not work. Nor
IsEqualsTonorIsEquivalentToworks for me.
await Assert.That(input.ОписПереміщення).IsEquivalentTo(new (ПосиланняНаПоле ІсходнеПоле, ПосиланняНаПоле[] ЦільовіПоля)[] {
(new ПосиланняНаПоле("PRODUCT-NO", 'A'), [new ПосиланняНаПоле("PRODUCT-NO", 'W')]),
(new ПосиланняНаПоле("QUANTITY", 'A'), [new ПосиланняНаПоле("QUANTITY", 'W')]),
});
Summary
Overall I think migration process even for small set of 13 tests which I have , is very painful to my taste.
Hi,
I really like what I have seen until now from TUnit and would like to convert our XUnit tests to TUnit. I use a lot IsType and Single, which is very helpful, because it returns the result to do further testing with it. I thought about to write own Asserts, but I don't know how to return a value I can use in the next steps. It seems it is not intended to have a result of an Assert. Is this planned for the next time?
Thanks
@kant2002 I'm sorry that you have to make changes but it's a different framework so it's expected to have API differences. I didn't set out to copy the xUnit API exactly. So unfortunately it will be a bit of a manual task for now.
It's actually probably possible to create analyzers with code fixes to help automate the process but that will be quite a big task so it would take quite a bit of time and effort to implement.
Hi,
I really like what I have seen until now from TUnit and would like to convert our XUnit tests to TUnit. I use a lot IsType and Single, which is very helpful, because it returns the result to do further testing with it. I thought about to write own Asserts, but I don't know how to return a value I can use in the next steps. It seems it is not intended to have a result of an Assert. Is this planned for the next time?
Thanks
Heya. Returning values sounds like it could be useful and doable. Leave this with me !
@thomhurst I did not expect API match one-2-one, but most other frameworks, at least for smaller projects can be very easiely migrated, since a lot of things converge.
It would be hard sell to migrate to your framework for existing codebases IMO, where benefits would be move prominent. I mean, I wrote this only to give you hint on how painful would be migrate existing tests suites. I bet MsTest would be the same deal.
The more users you could steal from others, the better to shake status quo a bit 😄 .
@kant2002 If it helps at all, when I did this I used a few cycles of regex find and replace and it wasn't incredibly painful.
@Xen0byte maybe it make sense to share it, even if not for my sake, but for others? What do you think. Even if it’s rough probably still would be better
@kant2002, unfortunately I didn't save them, it was a quick-and-dirty on-the-fly thing, but in hindsight I should have. They're pretty easy to write, it took me about 30 minutes to do an entire solution with about 2.5k tests across multiple projects. The regular expressions would look like something along the lines of the following:
find: Assert.Equal((?<expected>.*), (?<actual>.*));
replace: await Assert.That(${actual}).IsEqualTo(${expected});
NOTE 1: For assertions (example above) I would strongly recommend getting rid of the xUnit assertions library reference before you do this, and not after, because it's easier to keep track of how much you've covered and how much is still pending, by means of the compiler being unhappy.
NOTE 2: Migrating constructors to setup methods, for instance, works roughly the same way, you just need to make sure you include \n for multi-line values.
What is the latest on this? I don't want to mimic the xUnit API, so the options are:
- manually migrate even with the pain points
- develop an analyzer + code fixes to help automatically convert projects where possible
Is #2 required? It obviously wouldn't get to 100% success, AND would be a substantial amount of work to implement.
I think, it would be good to separate the TUnit test framework and the assertions in two separate libraries, e.g.
-
TUnit.Frameworkcontains the testing infrastructure, but does not have any dependency or include any assertions -
TUnit.Assertionscontains the assertion library - when referencing
TUnititself, both the framework and assertions library are included.
This way, when a user wants to migrate from any other framework, he can first adapt the test attributes to use the TUnit framework but keep the "old" assertions, as he does not have conflicting static Assert classes. Once this step is successful, he can in a second step switch over to use the TUnit assertions (or some other framework like fluentassertions).
I think, it would be good to separate the TUnit test framework and the assertions in two separate libraries, e.g.
TUnit.Frameworkcontains the testing infrastructure, but does not have any dependency or include any assertionsTUnit.Assertionscontains the assertion library- when referencing
TUnititself, both the framework and assertions library are included.This way, when a user wants to migrate from any other framework, he can first adapt the test attributes to use the TUnit framework but keep the "old" assertions, as he does not have conflicting static
Assertclasses. Once this step is successful, he can in a second step switch over to use the TUnit assertions (or some other framework likefluentassertions).
This is already the case.
TUnit.Engine + TUnit.Assertions
I had a quick look at this testing framework and gave up almost immediately because of the async tests. The thing is I have ref structs and they don't play at all with async. My suggestion would be to have non async Assert methods.
I had a quick look at this testing framework and gave up almost immediately because of the async tests. The thing is I have
ref structsand they don't play at all with async. My suggestion would be to have non async Assert methods.
@dellamonica I would encourage you to look at using TUnit.Engine for the testing framework and FluentAssertions or xunit.v3.assert for the assertion library. Then you can have sync test methods.
I had a quick look at this testing framework and gave up almost immediately because of the async tests. The thing is I have
ref structsand they don't play at all with async. My suggestion would be to have non async Assert methods.@dellamonica I would encourage you to look at using
TUnit.Enginefor the testing framework andFluentAssertionsorxunit.v3.assertfor the assertion library. Then you can have sync test methods.
That actually went well, thanks.
Here is a Copilot prompt I used to convert some test files. The improvements are obvious. The only limitation I found was that if a file was bigger than 1000 lines it would not go further.
In the current file only
Assert.IsType<T>(a) becomes Assert.That(a).IsTypeOf(typeof(T)) and should be awaited.
Assert.True(a) becomes Assert.That(a).IsTrue() and should be awaited.
Assert.Single(a) becomes Assert.That(a).HasSingleItem() and should be awaited.
Assert.Null(a) becomes await Assert.That(a).IsNull()
Assert.NotNull(a) becomes await Assert.That(a).IsNotNull()
Assert.StartsWith(a, b) becomes await Assert.That(b).StartsWith(a)
Assert.Contains(a, b) becomes await Assert.That(b).Contains(a)
Assert.Throw<T>(a) becomes await Assert.That(a).Throws<T>()