Skip to content
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

Nunit console doesnt find selenium-manager.exe , works fine from visual studio #1488

Closed
saiparth opened this issue Sep 22, 2024 · 29 comments · Fixed by #1489
Closed

Nunit console doesnt find selenium-manager.exe , works fine from visual studio #1488

saiparth opened this issue Sep 22, 2024 · 29 comments · Fixed by #1489
Assignees
Labels
Milestone

Comments

@saiparth
Copy link

I downloaded nunit3-console.exe zip file and running from my local machine. Problem is seems nunit-console sets some path for execution and wont find already downloaded selenium-manager.
steps
Create nunit project in .net8 or .netcore3.1
add selenium dependency and add basic step to lunch browser like var driver=new ChromeDriver();
Run from visual studio and verify it works fine
Open cmd and run dotnet test and observe it works fine
dotnet test "LoggerDemo/bin/debug/net8.0/LoggerDemo.dll""
Now run below command and see it throws exception
C:\softi\nunit-console\bin\net8.0\nunit3-console.exe "LoggerDemo/bin/debug/net8.0/LoggerDemo.dll"

System.TypeInitializationException : The type initializer for 'OpenQA.Selenium.SeleniumManager' threw an exception. ----> OpenQA.Selenium.WebDriverException : Unable to locate or obtain Selenium Manager binary at C:\softi\nunit-console\bin\net8.0\selenium-manager\windows\selenium-manager.exe at OpenQA.Selenium.SeleniumManager.BinaryPaths(String arguments) at OpenQA.Selenium.DriverFinder.BinaryPaths() at OpenQA.Selenium.DriverFinder.GetDriverPath() at OpenQA.Selenium.Chromium.ChromiumDriver.GenerateDriverServiceCommandExecutor(DriverService service, DriverOptions options, TimeSpan commandTimeout) at OpenQA.Selenium.Chromium.ChromiumDriver..ctor(ChromiumDriverService service, ChromiumOptions options, TimeSpan commandTimeout) at OpenQA.Selenium.Chrome.ChromeDriver..ctor(ChromeDriverService service, ChromeOptions options, TimeSpan commandTimeout) at OpenQA.Selenium.Chrome.ChromeDriver..ctor(ChromeOptions options) at OpenQA.Selenium.Chrome.ChromeDriver..ctor() at LoggerDemo.UnitTest2.Test1(String adf, String[] dsf) in C:\Repo\LoggerDemo\LoggerDemo\UnitTest2.cs:line 20 at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor) at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span1 copyOfArgs, BindingFlags invokeAttr)
--WebDriverException
at OpenQA.Selenium.SeleniumManager..cctor()`

I have tried setting below still its not working
$env:SE_MANAGER_PATH="LoggerDemo\bin\Debug\net8.0\selenium-manager\windows"

@OsirisTerje
Copy link
Member

Moving this to the console repo.

@OsirisTerje OsirisTerje transferred this issue from nunit/nunit Sep 22, 2024
@saiparth
Copy link
Author

is there any command that I can tell nunit console to refer project dll path, as of now it appears that nunit takes nunit3-console.exe path as base

@CharliePoole
Copy link
Collaborator

@saiparth You are running the console runner out of a net-8.0 directory, but it's important to know exactly where you got that runner, which runner it is and what it targets. Is there an initial console header displayed? It contains info that would allow us to deduce what you are running. Unfortunately, we have three runners all called "nunit3-console.exe". :-(

It will also be helpful to know if you are referencing the vs adapter in the same runs where you use the console and, if so, which verson.

@saiparth
Copy link
Author

saiparth commented Sep 27, 2024

Hi @CharliePoole
I downloaded from nunit release
Uploading Bug.zip…

  1. Create new nunit project, add selenium dependency
  2. Add a test
    [Test] public void Test1() { var driver = new ChromeDriver { Url = "https://www.google.com" }; driver.Quit(); }
  3. Run the test from visual studio.
  4. run the Bug/dotnetTest.bat - see it works
  5. run Bug/nunitConsole.bat - there will be exception
    Unable to locate or obtain Selenium Manager binary at Bug\Bug\NUnit.Console-3.18.2\bin\net8.0\selenium-manager\windows\selenium-manager.exe
    the file after we build solution restored at Bug\Bug\bin\Debug\net8.0\selenium-manager\windows\selenium-manager.exe"

@saiparth
Copy link
Author

Uploading Bug.zip…
dotnet test "bin\Debug\net8.0\Bug.dll"
"NUnit.Console-3.18.2\bin\net8.0\nunit3-console.exe" "bin\Debug\net8.0\Bug.dll"
I have extracted zip file of nunit and placed beside csproj

@nvborisenko
Copy link
Contributor

Selenium uses AppContext.BaseDirectory to determine the location of test assembly, which is supposed to be a test assembly location in world of testing. In most cases it works good, but seems not in this particular case.

@CharliePoole
Copy link
Collaborator

@saiparth What happens if you use the .NET 6.0 runner from the zip file? Does error change?

@nvborisenko Thanks for that info. The question seems to be "Whose AppContext?" From the symptoms, I would guess it's using the context of the NUnit runner itself. This might be a way to simplify the issue. I'll write some tests to see what the value of AppContext.BaseDirectory is when running in various environments.

@saiparth
Copy link
Author

@CharliePoole
I see same error if i use .NET 6.0
`C:\Repo\Bug\Bug>"NUnit.Console-3.18.2\bin\net6.0\nunit3-console.exe" "bin\Debug\net8.0\Bug.dll"
NUnit NetCore Console Runner 3.18.2 (Release)
Copyright (c) 2022 Charlie Poole, Rob Prouse
29 September 2024 09:58:17

Runtime Environment
OS Version: Microsoft Windows 10.0.22631
Runtime: .NET 6.0.33

Test Files
bin\Debug\net8.0\Bug.dll

Errors, Failures and Warnings

  1. Error : Bug.Tests.Test1
    System.TypeInitializationException : The type initializer for 'OpenQA.Selenium.SeleniumManager' threw an exception.
    ----> System.TypeLoadException : Could not load type 'System.Runtime.InteropServices.OSPlatform' from assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.`

@CharliePoole
Copy link
Collaborator

I'm running a small test project that simply checks the value of AppContext.BasePath. It passes for .NET Framework and fails for both .NET 6.0 and 8.0. It also fails for both .NET 6.0 and .NET 8.0 when running the NetCore console runner.

Of course, the .NET Framework builds use an ApplicationDomain, which is where the basepath is set. I'll do some research about whether there is any downside to setting the basepath directly in the runner.

@CharliePoole
Copy link
Collaborator

In .NET 8.0 I'm able to use AppContext.SetData to change the base path used in my custom AssemblyLoadContext. That makes my test of AppContext.BasePath pass in .NET 8.0. Unfortunately, it breaks some other tests. It may be that the tests need to be changed, so I'll first have to examine that.

I'm posting my code here, from class TestAssemblyLoadContext for comment.

        public TestAssemblyLoadContext(string testAssemblyPath)
        {
            _resolver = new TestAssemblyResolver(this, testAssemblyPath);
            _basePath = Path.GetDirectoryName(testAssemblyPath);
            _runtimeResolver = new AssemblyDependencyResolver(testAssemblyPath);
#if NET8_0_OR_GREATER
            AppContext.SetData("APP_CONTEXT_BASE_DIRECTORY", _basePath);
#endif

Note that SetData is not exposed in .NET 6.0, so this is not possible. However. .NET 6.0 reaches end of support on November 12, so a .NET 8.0 solution may be all we need.

@nunit @OsirisTerje All

I'd appreciate ideas and comments from anyone who knows more than me about this, esp. about any pitfalls to watch out for. I have a suspicion that this may possibly allow us to simplify the current code we use to find dependencies and if we put it in I'll experiment with that further.

@OsirisTerje
Copy link
Member

@CharliePoole We have said earlier that we will support LTS for approx 6 months after end of MS support. It may also be longer, as we have seen before.

But I wonder if we could accept that this works for .net 8 and above only, even if other parts of NUnit also support net 6.

@CharliePoole
Copy link
Collaborator

@OsirisTerje Ha ha! Have you met me? I'm still a strong believer in backward compatibility.

But "support" needs to be defined by any team creating software. I think we did that in the Platform Support document.

That document distinguishes what tests we will run from what specific runner agents we provide. We didn't deal with the .NET Core runner at the time we approved it, so that will require some extra thought.

AFAIR the @nunit team as a whole (absent an engine team) never reviewed that document. Would that be useful at this point?

@OsirisTerje
Copy link
Member

OsirisTerje commented Sep 29, 2024

@CharliePoole Yes, I did, and .net 8 is to be supported 6 months after MS EoS. Which is May 2025.

@CharliePoole
Copy link
Collaborator

@OsirisTerje Sorry, I dont' understand "I did." Can you clarify? Also, I assume you meant .NET 6.0.

I'll clarify as well.

I agree completely with your suggestion "But I wonder if we could accept that this works for .net 8 and above only, even if other parts of NUnit also support net 6." That's exactly what I was implying in my own initial comment.

I re-commented for two reasons:

  1. "Supporting" a platform is vague and may mean several different things to different people. For Microsoft, for example, it primarily means "providing security patches" which we don't talk about at all. In the linked document, we distinguished between supporting tests that target a platform versus providing a runner or agent for that platform. We indicated we would support running tests for as long as feasible - possibly for years. We also said we would support existing runners and agents for "at least six months" after Microsoft's EOL. When you wrote "support net x" I think that referred tot he runners, but I'm not 100% sure and I imagine others might be in the same boat.

  2. I'm a "temp" here, aka "collaborator", at my own request, so I usually only disagree with you privately. You are always very receptive. However, I felt that your comment, made publicly, might leave the impression that I had suggested ending support for something. To be clear, I'm not advocating de-supporting anything at this time and I'm not in favor of dropping any runners or agents.

BTW, the linked document says nothing about the .NET Core runner. We limited ourselves to the standard runner and agents when we wrote it. I'm hoping to come up with some ideas about the .NET Core runner as a result of working on various issues like this one and I'll make some suggestions when I do.

FWIW here is what I mean when I just use the word "support" by itself...

We state that we do not support tests targeting .NET Standard. What that means is we actively examine the assembly and if it targets .NET Standard, we refuse to run the test. We could do the same for any platform. In fact, there are others where we do that, e.g. Silverlight, Compact Framework. We could refuse to run .NET Core 2.1 tests as well, but we do not. So, by that definition, we still "support" .NET Core 2.1, typically running the tests using a .NET Core 3.1 agent.

@CharliePoole
Copy link
Collaborator

@nunit In spite of the policy/personal digression, still looking for technical insights on whether setting the BaseDirectory directly is a good idea.

@OsirisTerje
Copy link
Member

@CharliePoole Sorry, I wasn't clear :-) I am very grateful for what you're doing! Just so that is said.

I just meant I was aware of that document, and I thought it matches what the team discussed earlier on this. I do seem to remember (but may be mistaken) that we actually read it at that time. Hard to remember everything, but all in all, we are in complete agreement here - THAT was what I was trying to express!

When it comes to "support", we seems to mean that it actually will not work with the newer version, and we will not do fixes in earlier versions. E.g. in the framework we do support both the 3.X and the 4.X series, and then the latest version of each. That said, we have actually done support on an earlier version when there has been pressing needs from someone that really really want it very badly, and they seem nice of course!

I have also experienced that the different parts we have do support frameworks differently. So if you run using the adapter, either VS or dotnet cmd line, you will have one (or even two) experience(s) (add to that the engine of possibly not the latest version is embedded). Using the console, another experience. Using NUnitLite, a third experience, and using Rider and their own runner, which relies on not the latest engine version, yet another experience. Also, in the first case, VS, the experience will also depends on which version of VS you're using, and it also seems to have a certain dependency not only on which version you run, but also on which has been installed on your machine. There are so many dimensions to this, I don't think we're able to set up a complete documented matrix for this, unfortunately.

About AppContext.BaseDirectory, I have understood it is meant to be a read-only property, and should not be changed. I do not have enough knowledge to understand potentially side effects on this, also when you have the custom AssemblyLoadContext. But I do get a kind of yellow flag here. Feels like that is what you also get, since you're asking.
Since @jnm2 works a lot with dotnet itself these days, perhaps he can give some comments here.

@nvborisenko
Copy link
Contributor

nvborisenko commented Sep 29, 2024

Regarding AppContext.BaseDirectory https://learn.microsoft.com/ru-ru/dotnet/api/system.appcontext.basedirectory?view=net-8.0#remarks:

This is a per-application domain property. Its value corresponds to the AppDomain.BaseDirectory property of the current application domain.

Reading it further https://learn.microsoft.com/en-us/dotnet/framework/app-domains/how-to-configure-an-application-domain:

You can provide the common language runtime with configuration information for a new application domain using the AppDomainSetup class. When creating your own application domains, the most important property is ApplicationBase.

I hope this might help.

EDIT: It is not relevant for .net core, please ignore me.

@CharliePoole
Copy link
Collaborator

@nvborisenko The first citation is relevant to .net core but the second is framework only. .NET Core contains a kind of skeleton implementation of AppDomain, but many methods throw exceptions, including creating a new AppDomain.

@CharliePoole
Copy link
Collaborator

@OsirisTerje

Yes, although it's possible to set AppContext.BaseDirectory for our custom load context by use of the SetData method, it makes me nervous as well. I can do experiments but I'd feel better if we had some more input. In addition to @jnm2, do you have any ms contacts who know more? I'm also reading the ms code on GitHub to see if I can find any more about it.

On support... I feel like we have clarified it between ourselves but nobody else was involved in the discussion with me and of course any team discussions are private, which is why I asked.

@CharliePoole
Copy link
Collaborator

CharliePoole commented Sep 30, 2024

I have found 28 GitHub projects using AppContext.SetData("APP_CONTEXT_BASE_DIRECTORY", ...), many using it in the same way as I propose, i.e. in the constructor of a custom AssemblyLoadContext. Looking at the code for AppContext itself, the constructor leaves it set to the directory of the entry assembly for the code that is running but doesn't populate any dictionaries in advance. That only happens once you start resolving assembly references using the new load context.

I can see that this could be a dangerous thing to do in the default context or in any context that had already built up a dictionary of loaded assemblies but I'm confident enough about this usage to create a PR for it.

@saiparth I have only tested that this leaves the BaseDirectory set correctly. You'll need to verify the result of using it with your own code after the PR is created and merged.

@saiparth
Copy link
Author

@CharliePoole
Sure will check it

@CharliePoole
Copy link
Collaborator

@saiparth You can try this using 3.18.3-dev00002. I predict it will work if you are using an agent via the standard runner but not if you are using the .NET Core runner. :-)

@saiparth
Copy link
Author

saiparth commented Oct 1, 2024

It dint work for . net core runner, could you please tell me how to check via the standard runner

@CharliePoole
Copy link
Collaborator

CharliePoole commented Oct 1, 2024

You'll find the standard runner in the net462 directory in the zip if that's what you are using. Or get it from nuget or chocolatey as NUnit.ConsoleRunner. It will run under .NET Framework but launch an agent to execute your tests.

Note that the zip file only exists for 3.18.1 and earlier.

@saiparth
Copy link
Author

saiparth commented Oct 2, 2024

@CharliePoole
Thank you very much.
`C:\Repo\Bug\Bug>"NUnit.ConsoleRunner.3.18.3-dev00004\tools\nunit3-console.exe" --agents=2 "bin\Debug\net8.0\Bug.dll"
NUnit Console Runner 3.18.3-dev00004 (Release)
Copyright (c) 2022 Charlie Poole, Rob Prouse
02 October 2024 12:06:14

Runtime Environment
OS Version: Microsoft Windows NT 6.2.9200.0
Runtime: .NET Framework CLR v4.0.30319.42000

Test Files
bin\Debug\net8.0\Bug.dll

Run Settings
DisposeRunners: True
WorkDirectory: C:\Repo\Bug\Bug
MaxAgents: 2
ImageRuntimeVersion: 4.0.30319
ImageTargetFrameworkName: .NETCoreApp,Version=v8.0
ImageRequiresX86: False
ImageRequiresDefaultAppDomainAssemblyResolver: False
TargetRuntimeFramework: netcore-8.0
NumberOfTestWorkers: 8

Test Run Summary
Overall result: Passed
Test Count: 1, Passed: 1, Failed: 0, Warnings: 0, Inconclusive: 0, Skipped: 0
Start time: 2024-10-02 06:36:14Z
End time: 2024-10-02 06:36:18Z
Duration: 3.487 seconds`

@CharliePoole
Copy link
Collaborator

@saiparth
Great! The 3.19 release will have a .NET 8.0 runner and engine, so it will work in that runner as well.

@CharliePoole
Copy link
Collaborator

Our MyGet feed now contains a new package, NUnit.ConsoleRunner.Net80, released at version 3.18.3-dev00006. It's the equivalent of NUnit.ConsoleRunner.NetCore but targets .NET 8.0 rather than 6.0.

The package itself is experimental at this time and feedback on it will help us decide what to do in the coming 3.19 release.

@saiparth
Copy link
Author

saiparth commented Oct 3, 2024

I tried 3.18.3-dev00006 on same project and works fine.

C:\Repo\Bug\Bug>"NUnit.ConsoleRunner.3.18.3-dev00006\tools\nunit3-console.exe" "bin\Debug\net8.0\Bug.dll"
NUnit Console Runner 3.18.3-dev00006 (Release)
Copyright (c) 2022 Charlie Poole, Rob Prouse
03 October 2024 17:24:55

Runtime Environment
   OS Version: Microsoft Windows NT 6.2.9200.0
   Runtime: .NET Framework CLR v4.0.30319.42000

Test Files
    bin\Debug\net8.0\Bug.dll


Run Settings
    DisposeRunners: True
    WorkDirectory: C:\Repo\Bug\Bug
    ImageRuntimeVersion: 4.0.30319
    ImageTargetFrameworkName: .NETCoreApp,Version=v8.0
    ImageRequiresX86: False
    ImageRequiresDefaultAppDomainAssemblyResolver: False
    TargetRuntimeFramework: netcore-8.0
    NumberOfTestWorkers: 8

Test Run Summary
  Overall result: Passed
  Test Count: 1, Passed: 1, Failed: 0, Warnings: 0, Inconclusive: 0, Skipped: 0
  Start time: 2024-10-03 11:54:55Z
    End time: 2024-10-03 11:55:00Z
    Duration: 4.926 seconds

@CharliePoole
Copy link
Collaborator

This issue has been resolved in version 3.18.3

The release is available on:
GitHub.
NuGet packages are also available NuGet.org and
Chocolatey Packages may be found at Chocolatey.org

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants