Skip to content

Calling NUnitLite from LINQpad, can't parse assembly path #3710

Description

@astrohart

I am a frequent user of LINQPad and I am trying to run some really quick unit-tests in LINQPad and I have done so by adding the NUnitLite NuGet package to my LINQPad query.

I went on this blog and they advised utiling NUnitLite and using the following code in a C# Program LINQPad query's Main() method:

void Main()
{
  new TextRunner().Execute(new[]{"--noheader"});
}

// Define other methods and classes here
[Test]
public void SomeTest()
{
  Assert.Pass();
}

Obviously, we're assuming that the NuGet has been added to the query and that all the proper namespaces are brought in.

Well, this does not work with the latest NUnitLite. The results I get are;

No test assembly was specified.

Usage: NUNITLITE-RUNNER assembly [options]
       USER-EXECUTABLE [options]

Runs a set of NUnitLite tests from the console.

Assembly:
      File name or path of the assembly from which to execute tests. Required
      when using the nunitlite-runner executable to run the tests. Not allowed
      when running a self-executing user test assembly.

Options:
      --test=NAMES           Comma-separated list of NAMES of tests to run or
                               explore. This option may be repeated.
      --testlist=PATH        File PATH containing a list of tests to run, one
                               per line. This option may be repeated.
      --prefilter=NAMES      Comma-separated list of NAMES of test classes or
                               namespaces to be loaded. This option may be
                               repeated.
      --where=EXPRESSION     Test selection EXPRESSION indicating what tests
                               will be run. See description below.
      --params, -p=VALUE     Define a test parameter.
      --timeout=MILLISECONDS Set timeout for each test case in MILLISECONDS.
      --seed=SEED            Set the random SEED used to generate test cases.
      --workers=NUMBER       Specify the NUMBER of worker threads to be used
                               in running tests. If not specified, defaults to
                               2 or the number of processors, whichever is
                               greater.
      --stoponerror          Stop run immediately upon any test failure or
                               error.
      --wait                 Wait for input before closing console window.
      --work=PATH            PATH of the directory to use for output files. If
                               not specified, defaults to the current
                               directory.
      --output, --out=PATH   File PATH to contain text output from the tests.
      --err=PATH             File PATH to contain error output from the tests.
      --result=SPEC          An output SPEC for saving the test results. This
                               option may be repeated.
      --explore[=SPEC]       Display or save test info rather than running
                               tests. Optionally provide an output SPEC for
                               saving the test info. This option may be
                               repeated.
      --noresult             Don't save any test results.
      --labels=VALUE         Specify whether to write test case names to the
                               output. Values: Off, On, All
      --test-name-format=VALUE
                             Non-standard naming pattern to use in generating
                               test names.
      --teamcity             Turns on use of TeamCity service messages.
      --trace=LEVEL          Set internal trace LEVEL.
                               Values: Off, Error, Warning, Info, Verbose (
                               Debug)
      --noheader, --noh      Suppress display of program information at start
                               of run.
      --nocolor, --noc       Displays console output without color.
      --help, -h             Display this message and exit.
      --version, -V          Display the header and exit.
Notes:
    * File names may be listed by themselves, with a relative path or 
      using an absolute path. Any relative path is based on the current 
      directory.

    * On Windows, options may be prefixed by a '/' character if desired

    * Options that take values may use an equal sign or a colon
      to separate the option from its value.

    * Several options that specify processing of XML output take
      an output specification as a value. A SPEC may take one of
      the following forms:
          --OPTION:filename
          --OPTION:filename;format=formatname

      The --result option may use any of the following formats:
          nunit3 - the native XML format for NUnit 3
          nunit2 - legacy XML format used by earlier releases of NUnit

      The --explore option may use any of the following formats:
          nunit3 - the native XML format for NUnit 3
          cases  - a text file listing the full names of all test cases.
      If --explore is used without any specification following, a list of
      test cases is output to the console.

And then a NullReferenceException is caught.

So, I tried to give it the assembly name as follows:

void Main()
{
    new TextRunner().Execute(new[] { $@"assembly {Assembly.GetAssembly(typeof(UserQuery)).Location}"});
}

/* ... tests ... */

I get:

NUnitLite 3.13.0 (.NET Framework 4.5)
Copyright (c) 2021 Charlie Poole, Rob Prouse

Runtime Environment
   OS Version: Microsoft Windows NT 10.0.19041.0 
  CLR Version: 4.0.30319.42000 

Test Files
    assembly D:\Users\Foo\AppData\Local\Temp\LINQPad5\_lahhlytm\query_qwchmc.dll

System.NotSupportedException: The given path's format is not supported.
   at System.Security.Util.StringExpressionSet.CanonicalizePath(String path, Boolean needFullPath)
   at System.Security.Util.StringExpressionSet.CreateListFromExpressions(String[] str, Boolean needFullPath)
   at System.Security.Permissions.FileIOPermission.AddPathList(FileIOPermissionAccess access, AccessControlActions control, String[] pathListOrig, Boolean checkForDuplicates, Boolean needFullPath, Boolean copyPathList)
   at System.Security.Permissions.FileIOPermission..ctor(FileIOPermissionAccess access, String path)
   at System.Reflection.AssemblyName.GetAssemblyName(String assemblyFile)
   at NUnit.Framework.Internal.AssemblyHelper.Load(String nameOrPath)
   at NUnitLite.TextRunner.Execute()

I am not 100% sure why I am getting a NotSupportedException here. There are no spaces in the path and it's a perfectly valid file name. I can highlight the path, copy it and paste it into File Explorer and there's a file that certainly exists at that path.

Suspected Issue: NUnitLite, instead of simply calling System.IO.File.Exists() on whatever value it's given for the assembly parameter (and being done with it), instead is laboriously trying to validate the path and stuff. I think this is hogwash.

Suggested Fix: Parse out whatever value is passed to assembly and simply call System.IO.File.Exists(path) on it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions