-
Notifications
You must be signed in to change notification settings - Fork 253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
v3.3.0 (and v3.3.1) breaks test: Could not load file or assembly in method with AssemblyInitialize attribute #2653
Comments
I do get that exception too with v3.3.0. But that's a subsequent error, because the registration of the arbitrary in To reproduce the other 2 exceptions, you have to enable all "Common Language Runtime Exceptions" and uncheck "Enable Just My Code". |
I don't know if it helps you with evaluating the issue, but I'm maintaining a project that integrates FsCheck with MsTest and I use MsTest + FsCheck in production. Upgrading MsTest to v3.3.0 breaks a lot of my production tests that depend on arbitrary registration (both locally and in the CI pipeline). |
I will have a look next week but I recall having done some change to enable |
I do confirm that with the repro and MSTest 3.2.2, the test pass while with 3.3.0 or 3.3.1 the test fails. I have done some changes in local to try to revert #2110 and despite the few debugging exceptions all gone, I still end up with the same FsCheck exception: With or without the changes, we are correctly able to call the content of the I'd recommend creating a bug on their side so they can provide some more insights. |
I got the same\similar problem in 3.3.0-3.3.1. |
@osexpert are you also using FsCheck? Would it be possible for you to provide a repro? |
Not using FsCheck. But I tried to reproduce the problem again, I may not have remembered it clearly.....
So I think...this exception may not be harmful since catched, but it is confusing when debugging failing tests, so confusing\scary, that I downgraded instantly:-) |
@Evangelink I guess I found the issue. FsCheck's arbitrary registration uses Up to v3.2.2, that is no issue as long as I don't run my tests in parallel. The [assembly: DoNotParallelize]
namespace TestProject;
[TestClass]
public class UnitTest
{
[AssemblyInitialize]
public static void InitAssembly(TestContext _)
{
Console.WriteLine($"'AssemblyInitialize' thread id: {Environment.CurrentManagedThreadId}");
}
[ClassInitialize]
public static void InitClass(TestContext _)
{
Console.WriteLine($"'ClassInitialize' thread id: {Environment.CurrentManagedThreadId}");
}
[TestMethod]
public void TestMethod()
{
Console.WriteLine($"'TestMethod' thread id: {Environment.CurrentManagedThreadId}");
}
} Produces an output like this:
|
So likely linked to this change where each callback is now invoked as task, which might end up running on different threads. https://github.com/microsoft/testfx/pull/2570/files I don't see a way to implement cancellation and still carry out the rest of the tests on the same thread. E.g. in this situation:
|
We need to use custom thread for that but this is IMO a new feature request. I understand this break is problematic but I am not super keen on considering this a bug/regression on our side as we are changing internals and the behavior wasn't a documented/supported behavior. |
Now that I know what's causing the issue, I can work around it. E.g., with a custom using FsCheck;
using System.Collections.Concurrent;
namespace MsTestRegression;
public class FsCheckTestMethodAttribute : TestMethodAttribute
{
static readonly ConcurrentDictionary<int, int> Threads = new();
public override Microsoft.VisualStudio.TestTools.UnitTesting.TestResult[] Execute(ITestMethod testMethod)
{
var threadId = Environment.CurrentManagedThreadId;
if (Threads.TryAdd(threadId, threadId))
{
Arb.Register<Arbitraries>();
}
return base.Execute(testMethod);
}
}
[TestClass]
public class TestClass
{
[FsCheckTestMethod]
public void TestMethod1()
{
Prop.ForAll((IEnumerable<int> x) => true).QuickCheckThrowOnFailure();
}
}
public class Arbitraries
{
public static Arbitrary<IEnumerable<T>> EnumArb<T>() => new EnumerableArb<T>();
}
public sealed class EnumerableArb<T> : Arbitrary<IEnumerable<T>>
{
public override Gen<IEnumerable<T>> Generator => Arb.Generate<List<T>>().Select(l => (IEnumerable<T>)l);
} Btw, FsCheck v3 will be out soon (there's already an RC3). FsCheck v3 completely changes the way arbitraries are registered. It no longer uses I'm ok with you closing the issue if you want to. Thanks to everyone for looking into it! |
There is some good news. Good luck with your release! |
I am seeing this issue in .Net 8. Update 4/12/24: No I am not using FsCheck (I actually didn't understand that FsCheck was part of this issue). I am using a plain old MSTest to test web services and serialization of XML. |
Can you confirm you are also using FsCheck? If not, could you provide a repro or give us some details about your scenario? FsCheck is relying on some internals of MSTest (not a documented or supported behavior) and we had to change this behavior to enable some new timeout features so we are stuck here. @Andreas-Dorfer do you know when the new version of FsCheck will be released? |
I also think this case should not be closed. It throws there (VSInstallPath property) even if VS >= 2017 is installed. It did not before and it is in concflict with the comment in the code. So there is a regression there IMO. It "works", but this makes it annoying to debug tests, you always get into this ugly COMException first and it is not very trustworthy (bad impression). |
It cannot be considered as regression as it's some internal exception being caught. If you debug runtime or most of the tools you will see such behavior happening. Yet I agree this is not the best experience and that's why I fixed it in #2654 that will be available as part of the 3.4 release. |
I would not consider a breaking change too, MSTest doesn't give any guarantee for what I know(I don't see documentation around it) on the nature of the threads that are running the "tests method", we only guarantee that the execution order is the expected one. We need the freedom to change it for more than one reason, timeout is one...but there're others that could come in future. |
I have the following test code that works with no issues up to v3.2.2, but fails with v3.3.0 and v3.3.1 (see MsTestRegression.zip for running example):
(I'm using FsCheck).
When I debug the test with v3.2.2, there are no exceptions. However, when I debug the test with v3.3.0 (or v3.3.1), there are two exceptions thrown.
First:
Second:
I think these exceptions cause the test to fail. It seems like something about loading assemblies in a method with the
AssemblyInitialize
attribute has changed with v3.3.0. The actual test methodTestMethod1
then fails becauseArb.Register<Arbitraries>()
doesn't work as expected.The test also fails with v3.3.0 when run from the CLI (but works with up to v3.2.2).
*) .net8
*) MSTest.TestFramework 3.3.1
*) Visual Studio 17.9.5
The text was updated successfully, but these errors were encountered: