├── .editorconfig ├── .gitignore ├── .travis.yml ├── LICENSE ├── NuGet.Config ├── README.md ├── Rebracer.xml ├── appveyor.yml ├── dotnet-test-nunit.sln ├── global.json ├── scripts ├── set-version.ps1 └── show-dotnet-info.ps1 ├── src └── dotnet-test-nunit │ ├── ColorConsole.cs │ ├── ColorConsoleWriter.cs │ ├── ColorStyle.cs │ ├── CommandLineOptions.cs │ ├── Env.cs │ ├── Extensions │ ├── SafeAttributeAccess.cs │ ├── ServiceMessage.cs │ ├── ServiceMessageAttr.cs │ ├── ServiceMessageWriter.cs │ ├── TeamCityEventListener.cs │ └── TestExtensions.cs │ ├── Interfaces │ └── ITestListener.cs │ ├── Navigation │ └── NavigationDataProvider.cs │ ├── Program.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── ResultReporter.cs │ ├── ReturnCodes.cs │ ├── Sinks │ ├── Messages.cs │ ├── RemoteTestDiscoverySink.cs │ ├── RemoteTestExecutionSink.cs │ └── RemoteTestSink.cs │ ├── TestListeners │ ├── BaseTestListener.cs │ ├── TestExecutionListener.cs │ └── TestExploreListener.cs │ ├── TestRunner.cs │ ├── dotnet-test-nunit.xproj │ └── project.json └── test ├── dotnet-test-nunit.test.runner ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── dotnet-test-nunit.test.runner.xproj └── project.json └── dotnet-test-nunit.test ├── ColorConsoleTests.cs ├── ColorStyleTests.cs ├── CommandLineOptionsTests.cs ├── EnvTests.cs ├── Extensions └── TestExtensionsTests.cs ├── Mocks ├── MockTestExecutionSink.cs └── MockTestExplorerSink.cs ├── Navigation ├── NavigationDataProviderTests.cs └── NavigationTestData.cs ├── Properties └── AssemblyInfo.cs ├── Sinks ├── BaseSinkTests.cs ├── RemoteTestDiscoverySinkTests.cs ├── RemoteTestExecutionSinkTests.cs └── RemoteTestSinkTests.cs ├── TestListeners ├── TestExecutionListenerTests.cs └── TestExplorerListenerTests.cs ├── dotnet-test-nunit.test.xproj └── project.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and 2 | # maintain consistent coding styles between 3 | # different editors and IDEs 4 | 5 | # http://EditorConfig.org 6 | 7 | # top-most EditorConfig file 8 | root = true 9 | 10 | [*] 11 | end_of_line = crlf 12 | indent_style = space 13 | indent_size = 2 14 | tab_width = 4 15 | trim_trailing_whitespace = true 16 | 17 | [*.cs] 18 | charset = utf-8 19 | indent_style = space 20 | indent_size = 4 21 | 22 | [*.json] 23 | charset = utf-8 24 | indent_style = space 25 | indent_size = 2 26 | 27 | [*.xproj] 28 | charset = utf-8 29 | indent_style = space 30 | indent_size = 2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | 24 | # Visual Studio 2015 cache/options directory 25 | .vs/ 26 | # Uncomment if you have tasks that create the project's static files in wwwroot 27 | #wwwroot/ 28 | 29 | # MSTest test Results 30 | [Tt]est[Rr]esult*/ 31 | [Bb]uild[Ll]og.* 32 | 33 | # NUNIT 34 | *.VisualState.xml 35 | TestResult.xml 36 | 37 | # Build Results of an ATL Project 38 | [Dd]ebugPS/ 39 | [Rr]eleasePS/ 40 | dlldata.c 41 | 42 | # DNX 43 | project.lock.json 44 | artifacts/ 45 | 46 | *_i.c 47 | *_p.c 48 | *_i.h 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.tmp_proj 63 | *.log 64 | *.vspscc 65 | *.vssscc 66 | .builds 67 | *.pidb 68 | *.svclog 69 | *.scc 70 | 71 | # Chutzpah Test files 72 | _Chutzpah* 73 | 74 | # Visual C++ cache files 75 | ipch/ 76 | *.aps 77 | *.ncb 78 | *.opendb 79 | *.opensdf 80 | *.sdf 81 | *.cachefile 82 | 83 | # Visual Studio profiler 84 | *.psess 85 | *.vsp 86 | *.vspx 87 | *.sap 88 | 89 | # TFS 2012 Local Workspace 90 | $tf/ 91 | 92 | # Guidance Automation Toolkit 93 | *.gpState 94 | 95 | # ReSharper is a .NET coding add-in 96 | _ReSharper*/ 97 | *.[Rr]e[Ss]harper 98 | *.DotSettings.user 99 | 100 | # JustCode is a .NET coding add-in 101 | .JustCode 102 | 103 | # TeamCity is a build add-in 104 | _TeamCity* 105 | 106 | # DotCover is a Code Coverage Tool 107 | *.dotCover 108 | 109 | # NCrunch 110 | _NCrunch_* 111 | .*crunch*.local.xml 112 | nCrunchTemp_* 113 | 114 | # MightyMoose 115 | *.mm.* 116 | AutoTest.Net/ 117 | 118 | # Web workbench (sass) 119 | .sass-cache/ 120 | 121 | # Installshield output folder 122 | [Ee]xpress/ 123 | 124 | # DocProject is a documentation generator add-in 125 | DocProject/buildhelp/ 126 | DocProject/Help/*.HxT 127 | DocProject/Help/*.HxC 128 | DocProject/Help/*.hhc 129 | DocProject/Help/*.hhk 130 | DocProject/Help/*.hhp 131 | DocProject/Help/Html2 132 | DocProject/Help/html 133 | 134 | # Click-Once directory 135 | publish/ 136 | 137 | # Publish Web Output 138 | *.[Pp]ublish.xml 139 | *.azurePubxml 140 | # TODO: Comment the next line if you want to checkin your web deploy settings 141 | # but database connection strings (with potential passwords) will be unencrypted 142 | *.pubxml 143 | *.publishproj 144 | 145 | # NuGet Packages 146 | *.nupkg 147 | # The packages folder can be ignored because of Package Restore 148 | **/packages/* 149 | # except build/, which is used as an MSBuild target. 150 | !**/packages/build/ 151 | # Uncomment if necessary however generally it will be regenerated when needed 152 | #!**/packages/repositories.config 153 | # NuGet v3's project.json files produces more ignoreable files 154 | *.nuget.props 155 | *.nuget.targets 156 | 157 | # Microsoft Azure Build Output 158 | csx/ 159 | *.build.csdef 160 | 161 | # Microsoft Azure Emulator 162 | ecf/ 163 | rcf/ 164 | 165 | # Microsoft Azure ApplicationInsights config file 166 | ApplicationInsights.config 167 | 168 | # Windows Store app package directory 169 | AppPackages/ 170 | BundleArtifacts/ 171 | 172 | # Visual Studio cache files 173 | # files ending in .cache can be ignored 174 | *.[Cc]ache 175 | # but keep track of directories ending in .cache 176 | !*.[Cc]ache/ 177 | 178 | # Others 179 | ClientBin/ 180 | ~$* 181 | *~ 182 | *.dbmdl 183 | *.dbproj.schemaview 184 | *.pfx 185 | *.publishsettings 186 | node_modules/ 187 | orleans.codegen.cs 188 | 189 | # RIA/Silverlight projects 190 | Generated_Code/ 191 | 192 | # Backup & report files from converting an old project file 193 | # to a newer Visual Studio version. Backup files are not needed, 194 | # because we have git ;-) 195 | _UpgradeReport_Files/ 196 | Backup*/ 197 | UpgradeLog*.XML 198 | UpgradeLog*.htm 199 | 200 | # SQL Server files 201 | *.mdf 202 | *.ldf 203 | 204 | # Business Intelligence projects 205 | *.rdl.data 206 | *.bim.layout 207 | *.bim_*.settings 208 | 209 | # Microsoft Fakes 210 | FakesAssemblies/ 211 | 212 | # GhostDoc plugin setting file 213 | *.GhostDoc.xml 214 | 215 | # Node.js Tools for Visual Studio 216 | .ntvs_analysis.dat 217 | 218 | # Visual Studio 6 build log 219 | *.plg 220 | 221 | # Visual Studio 6 workspace options file 222 | *.opt 223 | 224 | # Visual Studio LightSwitch build output 225 | **/*.HTMLClient/GeneratedArtifacts 226 | **/*.DesktopClient/GeneratedArtifacts 227 | **/*.DesktopClient/ModelManifest.xml 228 | **/*.Server/GeneratedArtifacts 229 | **/*.Server/ModelManifest.xml 230 | _Pvt_Extensions 231 | 232 | # Paket dependency manager 233 | .paket/paket.exe 234 | 235 | # FAKE - F# Make 236 | .fake/ 237 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | 3 | addons: 4 | apt: 5 | packages: 6 | - gettext 7 | - libcurl4-openssl-dev 8 | - libicu-dev 9 | - libssl-dev 10 | - libunwind8 11 | - zlib1g 12 | 13 | matrix: 14 | include: 15 | - os: linux 16 | dist: trusty # Ubuntu 14.04 17 | sudo: required 18 | env: CONFIGURATION=Debug 19 | - os: linux 20 | dist: trusty 21 | sudo: required 22 | env: CONFIGURATION=Release 23 | - os: osx 24 | osx_image: xcode7.2 # macOS 10.11 25 | env: CONFIGURATION=Debug 26 | - os: osx 27 | osx_image: xcode7.2 28 | env: CONFIGURATION=Release 29 | 30 | before_install: 31 | # Install OpenSSL 32 | - if test "$TRAVIS_OS_NAME" == "osx"; then 33 | brew install openssl; 34 | brew link --force openssl; 35 | export DOTNET_SDK_URL="https://go.microsoft.com/fwlink/?LinkID=809128"; 36 | else 37 | export DOTNET_SDK_URL="https://go.microsoft.com/fwlink/?LinkID=809129"; 38 | fi 39 | 40 | - export DOTNET_INSTALL_DIR="$PWD/.dotnetcli" 41 | 42 | # Install .NET CLI 43 | - mkdir $DOTNET_INSTALL_DIR 44 | - curl -L $DOTNET_SDK_URL -o dotnet_package 45 | - tar -xvzf dotnet_package -C $DOTNET_INSTALL_DIR 46 | 47 | # Add dotnet to PATH 48 | - export PATH="$DOTNET_INSTALL_DIR:$PATH" 49 | 50 | install: 51 | # Display dotnet version info 52 | - which dotnet; 53 | if [ $? -eq 0 ]; then 54 | echo "Using dotnet:"; 55 | dotnet --info; 56 | else 57 | echo "dotnet.exe not found" 58 | exit 1; 59 | fi 60 | 61 | # [WORKAROUND] 62 | # 63 | # SYNOPSIS: 64 | # 65 | # dotnet-cli has introduced a bug with .NET Core RTM (wasn't there till RC2); 66 | # that is, the dotnet-run command ignores --framework option and therefore 67 | # demands mono PCL reference assemblies to be present on Unix systems, even 68 | # though when we intend to build for netcoreapp or netstandard TxM. 69 | # 70 | # See: https://github.com/dotnet/cli/issues/3658 71 | # 72 | # The workaround is to rewrite the JSON without net451 framework node in the 73 | # runnable (or testable) project's JSON file for CI. This work around must be 74 | # applied before executing dotnet-restore command. 75 | # 76 | # Written in JavaScript to be executable with node.js 77 | # (JavaScript being the most native langauge for JSON processing) 78 | # 79 | # Travis CI job when running under different langauge provides nvm (the node.js version manager) 80 | # but not node.js itself. So we first run: 81 | # 82 | # > $HOME/.nvm/nvm.sh 83 | # 84 | # then install stable node 85 | # 86 | # > nvm install stable && nvm use stable 87 | # 88 | # now, we have node.js in PATH. We will run the following program in evaluation 89 | # mode as one-liner: 90 | # 91 | # ```javascript 92 | # // the file to manipulate 93 | # jsonPath = './test/dotnet-test-nunit.test.runner/project.json'; 94 | # 95 | # // read and parse JSON as object (aka CommonJS magic) 96 | # data = require(jsonPath); 97 | # 98 | # // FileSystem API handle 99 | # fs = require('fs'); 100 | # 101 | # // delete framework 451 key from the object 102 | # delete data.frameworks.net451; 103 | # 104 | # // write back to file 105 | # fs.writeFileSync(jsonPath, JSON.stringify(data, null, 2)); 106 | # ``` 107 | # Now the actual one-liner (compressed) version: 108 | # 109 | - if test "$TRAVIS_OS_NAME" == "linux"; then 110 | nvm install stable && nvm use stable; 111 | fi 112 | - node -e "jsonPath='./test/dotnet-test-nunit.test.runner/project.json';data=require(jsonPath);fs=require('fs');delete data.frameworks.net451;fs.writeFileSync(jsonPath, JSON.stringify(data, null, 2))" 113 | 114 | # Restore dependencies 115 | - dotnet restore 116 | 117 | # Build projects 118 | - dotnet build -c $CONFIGURATION -f netcoreapp1.0 ./test/dotnet-test-nunit.test.runner 119 | 120 | script: 121 | # Run tests 122 | - dotnet run -c $CONFIGURATION -f netcoreapp1.0 -p ./test/dotnet-test-nunit.test.runner 123 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 NUnit Project 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NUnit 3 Test Runner for .NET Core 2 | 3 | ## Deprecated 4 | 5 | This project is deprecated. The test adapter API changed when .NET Core switched from 6 | `project.json` to the new `csproj` format. For newer .NET Core and .NET Standard 7 | projects, use the [NUnit 3 Visual Studio Test adapter](https://github.com/nunit/nunit3-vs-adapter) 8 | to run tests at the command line using `dotnet test`, in CI or in Visual Studio. 9 | 10 | For more information on how to test .NET Core, see the 11 | [.NET Core/.NET Standard documentation](https://github.com/nunit/docs/wiki/.NET-Core-and-.NET-Standard). 12 | 13 | If you are reporting **issues**, we are no longer making updates to this project or the use of `dotnet-test-nunit` and `project.json`. Issues should be reported against the [NUnit 3 Visual Studio Test adapter](https://github.com/nunit/nunit3-vs-adapter). 14 | 15 | 16 | [![Build status](https://ci.appveyor.com/api/projects/status/yg7dawcy1106g1li/branch/master?svg=true)](https://ci.appveyor.com/project/CharliePoole/dotnet-test-nunit/branch/master) [![Travis Build Status](https://travis-ci.org/nunit/dotnet-test-nunit.svg?branch=master)](https://travis-ci.org/nunit/dotnet-test-nunit) 17 | 18 | `dotnet-test-nunit` is the unit test runner for .NET Core for running unit tests with NUnit 3. 19 | 20 | ## Usage 21 | 22 | `dotnet-test-nunit` is still an alpha release, so you need to select `show prereleases` if you are using Visual Studio. 23 | 24 | Your `project.json` in your test project should look like the following; 25 | 26 | ### project.json 27 | 28 | ```json 29 | { 30 | "version": "1.0.0-*", 31 | 32 | "dependencies": { 33 | "NUnit": "3.5.0", 34 | "dotnet-test-nunit": "3.4.0-beta-3" 35 | }, 36 | 37 | "testRunner": "nunit", 38 | 39 | "frameworks": { 40 | "netcoreapp1.0": { 41 | "imports": "portable-net45+win8", 42 | "dependencies": { 43 | "Microsoft.NETCore.App": { 44 | "version": "1.0.0-*", 45 | "type": "platform" 46 | } 47 | } 48 | } 49 | } 50 | } 51 | ``` 52 | 53 | The lines of interest here are the dependency on `dotnet-test-nunit`. I have added `"testRunner": "nunit"` to specify NUnit 3 as the test adapter. I also had to add to the imports for both the test adapter and NUnit to resolve. 54 | 55 | You can now run your tests using the Visual Studio Test Explorer, or by running `dotnet test` from the command line. 56 | 57 | ```sh 58 | # Restore the NuGet packages 59 | dotnet restore 60 | 61 | # Run the unit tests in the current directory 62 | dotnet test 63 | 64 | # Run the unit tests in a different directory 65 | dotnet test test/NUnitWithDotNetCoreRC2.Test 66 | ``` 67 | 68 | ### Notes 69 | 70 | Note that the `dotnet` command line swallows blank lines and does not work with color. 71 | The NUnit test runner's output is in color, but you won't see it. These are known issues with 72 | the `dotnet` CLI and not an NUnit bug. 73 | -------------------------------------------------------------------------------- /Rebracer.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 0 13 | 0 14 | 1 15 | 1 16 | 1 17 | -1 18 | -1 19 | 1 20 | 2 21 | 80 22 | 0 23 | 1 24 | 0 25 | 1 26 | 1 27 | 1 28 | 1 29 | 0 30 | 1 31 | 0 32 | 1 33 | 1 34 | 0 35 | 1 36 | 1 37 | 1 38 | 1 39 | 1 40 | 0 41 | 0 42 | 1 43 | 1 44 | 1 45 | 1 46 | 1 47 | 1 48 | 1 49 | 1 50 | 1 51 | 1 52 | 1 53 | 1 54 | 1 55 | 1 56 | 1 57 | 1 58 | 0 59 | 1 60 | 0 61 | 1 62 | 0 63 | 0 64 | 1 65 | 1 66 | 1 67 | 0 68 | 0 69 | 1 70 | 0 71 | 0 72 | 0 73 | 0 74 | 0 75 | 1 76 | 0 77 | 0 78 | 0 79 | 0 80 | 0 81 | 0 82 | 0 83 | 1 84 | 1 85 | 0 86 | 1 87 | 0 88 | 1 89 | 0 90 | 0 91 | 1 92 | 1 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 3.3.0.{build} 2 | os: Visual Studio 2015 3 | configuration: Release 4 | 5 | assembly_info: 6 | patch: true 7 | file: '**\AssemblyInfo.*' 8 | assembly_version: '{version}' 9 | assembly_file_version: '{version}' 10 | 11 | before_build: 12 | - ps: .\scripts\show-dotnet-info.ps1 13 | - ps: .\scripts\set-version.ps1 14 | - cmd: dotnet --info 15 | - cmd: dotnet restore 16 | 17 | build_script: 18 | - cmd: dotnet build -c Release test\dotnet-test-nunit.test.runner\ 19 | 20 | test_script: 21 | - cmd: dotnet run -c Release -p test\dotnet-test-nunit.test.runner\ 22 | 23 | after_test: 24 | - cmd: dotnet pack -c Release src\dotnet-test-nunit\ 25 | 26 | test: off 27 | 28 | artifacts: 29 | path: 'src\dotnet-test-nunit\bin\Release\*.nupkg' 30 | -------------------------------------------------------------------------------- /dotnet-test-nunit.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F0FC9C69-996D-43E7-B8A0-35A9311E2B36}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3D935F98-183C-4E6F-99C0-D166B0FC0F33}" 9 | ProjectSection(SolutionItems) = preProject 10 | .editorconfig = .editorconfig 11 | .gitignore = .gitignore 12 | .travis.yml = .travis.yml 13 | appveyor.yml = appveyor.yml 14 | global.json = global.json 15 | NuGet.Config = NuGet.Config 16 | README.md = README.md 17 | Rebracer.xml = Rebracer.xml 18 | EndProjectSection 19 | EndProject 20 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-test-nunit", "src\dotnet-test-nunit\dotnet-test-nunit.xproj", "{7FC6DCED-278A-449B-8BB0-95346410C8D2}" 21 | EndProject 22 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{93336E7C-25F0-4327-84EA-B190EA537709}" 23 | EndProject 24 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-test-nunit.test", "test\dotnet-test-nunit.test\dotnet-test-nunit.test.xproj", "{B3C98A50-D42F-4197-968B-0E25591E83C3}" 25 | EndProject 26 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-test-nunit.test.runner", "test\dotnet-test-nunit.test.runner\dotnet-test-nunit.test.runner.xproj", "{F2025265-8A4E-46DD-AE91-537E302B3F24}" 27 | EndProject 28 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{D519507E-757D-4B9F-9B02-8E8E0B64071A}" 29 | ProjectSection(SolutionItems) = preProject 30 | scripts\set-version.ps1 = scripts\set-version.ps1 31 | scripts\show-dotnet-info.ps1 = scripts\show-dotnet-info.ps1 32 | EndProjectSection 33 | EndProject 34 | Global 35 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 36 | Debug|Any CPU = Debug|Any CPU 37 | Release|Any CPU = Release|Any CPU 38 | EndGlobalSection 39 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 40 | {7FC6DCED-278A-449B-8BB0-95346410C8D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {7FC6DCED-278A-449B-8BB0-95346410C8D2}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {7FC6DCED-278A-449B-8BB0-95346410C8D2}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {7FC6DCED-278A-449B-8BB0-95346410C8D2}.Release|Any CPU.Build.0 = Release|Any CPU 44 | {B3C98A50-D42F-4197-968B-0E25591E83C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {B3C98A50-D42F-4197-968B-0E25591E83C3}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | {B3C98A50-D42F-4197-968B-0E25591E83C3}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {B3C98A50-D42F-4197-968B-0E25591E83C3}.Release|Any CPU.Build.0 = Release|Any CPU 48 | {F2025265-8A4E-46DD-AE91-537E302B3F24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 49 | {F2025265-8A4E-46DD-AE91-537E302B3F24}.Debug|Any CPU.Build.0 = Debug|Any CPU 50 | {F2025265-8A4E-46DD-AE91-537E302B3F24}.Release|Any CPU.ActiveCfg = Release|Any CPU 51 | {F2025265-8A4E-46DD-AE91-537E302B3F24}.Release|Any CPU.Build.0 = Release|Any CPU 52 | EndGlobalSection 53 | GlobalSection(SolutionProperties) = preSolution 54 | HideSolutionNode = FALSE 55 | EndGlobalSection 56 | GlobalSection(NestedProjects) = preSolution 57 | {7FC6DCED-278A-449B-8BB0-95346410C8D2} = {F0FC9C69-996D-43E7-B8A0-35A9311E2B36} 58 | {B3C98A50-D42F-4197-968B-0E25591E83C3} = {93336E7C-25F0-4327-84EA-B190EA537709} 59 | {F2025265-8A4E-46DD-AE91-537E302B3F24} = {93336E7C-25F0-4327-84EA-B190EA537709} 60 | EndGlobalSection 61 | EndGlobal 62 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "projects": [ "src", "test" ], 3 | "sdk": { 4 | "version": "1.0.0-preview2-003131" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /scripts/set-version.ps1: -------------------------------------------------------------------------------- 1 | $ReleaseVersionNumber = $env:APPVEYOR_BUILD_VERSION 2 | $PreReleaseName = '' 3 | 4 | If($env:APPVEYOR_PULL_REQUEST_NUMBER -ne $null) { 5 | $PreReleaseName = '-PR-' + $env:APPVEYOR_PULL_REQUEST_NUMBER 6 | } ElseIf($env:APPVEYOR_REPO_BRANCH -ne 'master' -and -not $env:APPVEYOR_REPO_BRANCH.StartsWith('release')) { 7 | $PreReleaseName = '-' + $env:APPVEYOR_REPO_BRANCH 8 | } Else { 9 | $PreReleaseName = '-CI' 10 | } 11 | 12 | $PSScriptFilePath = (Get-Item $MyInvocation.MyCommand.Path).FullName 13 | $ScriptDir = Split-Path -Path $PSScriptFilePath -Parent 14 | $SolutionRoot = Split-Path -Path $ScriptDir -Parent 15 | 16 | $ProjectJsonPath = Join-Path -Path $SolutionRoot -ChildPath "src\dotnet-test-nunit\project.json" 17 | $re = [regex]"(?<=`"version`":\s`")[.\w-]*(?=`",)" 18 | $re.Replace([string]::Join("`n", (Get-Content -Path $ProjectJsonPath)), "$ReleaseVersionNumber$PreReleaseName", 1) | 19 | Set-Content -Path $ProjectJsonPath -Encoding UTF8 -------------------------------------------------------------------------------- /scripts/show-dotnet-info.ps1: -------------------------------------------------------------------------------- 1 | if (Get-Command dotnet -errorAction SilentlyContinue) { 2 | Write-Host "Using dotnet '$((Get-Command dotnet).Path)'" 3 | dotnet --version 4 | } 5 | else { 6 | Write-Host "dotnet.exe not found" 7 | } -------------------------------------------------------------------------------- /src/dotnet-test-nunit/ColorConsole.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | 26 | namespace NUnit.Runner 27 | { 28 | /// 29 | /// Sets the console color in the constructor and resets it in the dispose 30 | /// 31 | public class ColorConsole : IDisposable 32 | { 33 | private ConsoleColor _originalColor; 34 | 35 | /// 36 | /// Initializes a new instance of the class. 37 | /// 38 | /// The color style to use. 39 | public ColorConsole(ColorStyle style) 40 | { 41 | _originalColor = Console.ForegroundColor; 42 | Console.ForegroundColor = GetColor(style); 43 | } 44 | 45 | /// 46 | /// By using styles, we can keep everything consistent 47 | /// 48 | /// 49 | /// 50 | public static ConsoleColor GetColor(ColorStyle style) 51 | { 52 | ConsoleColor color = GetColorForStyle(style); 53 | ConsoleColor bg = Console.BackgroundColor; 54 | 55 | if (color == bg || color == ConsoleColor.Red && bg == ConsoleColor.Magenta) 56 | return bg == ConsoleColor.Black 57 | ? ConsoleColor.White 58 | : ConsoleColor.Black; 59 | 60 | return color; 61 | } 62 | 63 | private static ConsoleColor GetColorForStyle(ColorStyle style) 64 | { 65 | switch (Console.BackgroundColor) 66 | { 67 | case ConsoleColor.White: 68 | switch (style) 69 | { 70 | case ColorStyle.Header: 71 | return ConsoleColor.Black; 72 | case ColorStyle.SubHeader: 73 | return ConsoleColor.Black; 74 | case ColorStyle.SectionHeader: 75 | return ConsoleColor.Blue; 76 | case ColorStyle.Label: 77 | return ConsoleColor.Black; 78 | case ColorStyle.Value: 79 | return ConsoleColor.Blue; 80 | case ColorStyle.Pass: 81 | return ConsoleColor.Green; 82 | case ColorStyle.Failure: 83 | return ConsoleColor.Red; 84 | case ColorStyle.Warning: 85 | return ConsoleColor.Black; 86 | case ColorStyle.Error: 87 | return ConsoleColor.Red; 88 | case ColorStyle.Output: 89 | return ConsoleColor.Black; 90 | case ColorStyle.Help: 91 | return ConsoleColor.Black; 92 | case ColorStyle.Default: 93 | default: 94 | return ConsoleColor.Black; 95 | } 96 | 97 | case ConsoleColor.Cyan: 98 | case ConsoleColor.Green: 99 | case ConsoleColor.Red: 100 | case ConsoleColor.Magenta: 101 | case ConsoleColor.Yellow: 102 | switch (style) 103 | { 104 | case ColorStyle.Header: 105 | return ConsoleColor.Black; 106 | case ColorStyle.SubHeader: 107 | return ConsoleColor.Black; 108 | case ColorStyle.SectionHeader: 109 | return ConsoleColor.Blue; 110 | case ColorStyle.Label: 111 | return ConsoleColor.Black; 112 | case ColorStyle.Value: 113 | return ConsoleColor.Black; 114 | case ColorStyle.Pass: 115 | return ConsoleColor.Black; 116 | case ColorStyle.Failure: 117 | return ConsoleColor.Red; 118 | case ColorStyle.Warning: 119 | return ConsoleColor.Yellow; 120 | case ColorStyle.Error: 121 | return ConsoleColor.Red; 122 | case ColorStyle.Output: 123 | return ConsoleColor.Black; 124 | case ColorStyle.Help: 125 | return ConsoleColor.Black; 126 | case ColorStyle.Default: 127 | default: 128 | return ConsoleColor.Black; 129 | } 130 | 131 | default: 132 | switch (style) 133 | { 134 | case ColorStyle.Header: 135 | return ConsoleColor.White; 136 | case ColorStyle.SubHeader: 137 | return ConsoleColor.Gray; 138 | case ColorStyle.SectionHeader: 139 | return ConsoleColor.Cyan; 140 | case ColorStyle.Label: 141 | return ConsoleColor.Green; 142 | case ColorStyle.Value: 143 | return ConsoleColor.White; 144 | case ColorStyle.Pass: 145 | return ConsoleColor.Green; 146 | case ColorStyle.Failure: 147 | return ConsoleColor.Red; 148 | case ColorStyle.Warning: 149 | return ConsoleColor.Yellow; 150 | case ColorStyle.Error: 151 | return ConsoleColor.Red; 152 | case ColorStyle.Output: 153 | return ConsoleColor.Gray; 154 | case ColorStyle.Help: 155 | return ConsoleColor.Green; 156 | case ColorStyle.Default: 157 | default: 158 | return ConsoleColor.Green; 159 | } 160 | } 161 | } 162 | 163 | #region Implementation of IDisposable 164 | 165 | /// 166 | /// If color is enabled, restores the console colors to their defaults 167 | /// 168 | public void Dispose() 169 | { 170 | Console.ForegroundColor = _originalColor; 171 | } 172 | 173 | #endregion 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/ColorConsoleWriter.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.IO; 26 | using System.Text; 27 | 28 | namespace NUnit.Runner 29 | { 30 | public class ColorConsoleWriter 31 | { 32 | bool _colorEnabled; 33 | TextWriter _writer; 34 | 35 | /// 36 | /// Construct a ColorConsoleWriter. 37 | /// 38 | public ColorConsoleWriter() : this(true) { } 39 | 40 | /// 41 | /// Construct a ColorConsoleWriter. 42 | /// 43 | /// Flag indicating whether color should be enabled 44 | public ColorConsoleWriter(bool colorEnabled) 45 | { 46 | _writer = Console.Out; 47 | _colorEnabled = colorEnabled; 48 | } 49 | 50 | #region Extended Methods 51 | /// 52 | /// Writes the value with the specified style. 53 | /// 54 | /// The style. 55 | /// The value. 56 | public void Write(ColorStyle style, string value) 57 | { 58 | if (_colorEnabled) 59 | using (new ColorConsole(style)) 60 | { 61 | _writer.Write(value); 62 | } 63 | else 64 | _writer.Write(value); 65 | } 66 | 67 | /// 68 | /// Writes the value with the specified style. 69 | /// 70 | /// The style. 71 | /// The value. 72 | public void WriteLine(ColorStyle style, string value) 73 | { 74 | if (_colorEnabled) 75 | using (new ColorConsole(style)) 76 | { 77 | _writer.WriteLine(value); 78 | } 79 | else 80 | _writer.WriteLine(value); 81 | } 82 | 83 | /// 84 | /// Writes the label and the option that goes with it. 85 | /// 86 | /// The label. 87 | /// The option. 88 | public void WriteLabel(string label, object option) 89 | { 90 | WriteLabel(label, option, ColorStyle.Value); 91 | } 92 | 93 | /// 94 | /// Writes the label and the option that goes with it followed by a new line. 95 | /// 96 | /// The label. 97 | /// The option. 98 | public void WriteLabelLine(string label, object option) 99 | { 100 | WriteLabelLine(label, option, ColorStyle.Value); 101 | } 102 | 103 | /// 104 | /// Writes the label and the option that goes with it and optionally writes a new line. 105 | /// 106 | /// The label. 107 | /// The option. 108 | /// The color to display the value with 109 | public void WriteLabel(string label, object option, ColorStyle valueStyle) 110 | { 111 | Write(ColorStyle.Label, label); 112 | Write(valueStyle, option.ToString()); 113 | } 114 | 115 | /// 116 | /// Writes the label and the option that goes with it followed by a new line. 117 | /// 118 | /// The label. 119 | /// The option. 120 | /// The color to display the value with 121 | public void WriteLabelLine(string label, object option, ColorStyle valueStyle) 122 | { 123 | WriteLabel(label, option, valueStyle); 124 | _writer.WriteLine(); 125 | } 126 | 127 | /// 128 | /// Write a single char value 129 | /// 130 | public void Write(char value) 131 | { 132 | _writer.Write(value); 133 | } 134 | 135 | /// 136 | /// Write a string value 137 | /// 138 | public void Write(string value) 139 | { 140 | _writer.Write(value); 141 | } 142 | 143 | /// 144 | /// Writes a NewLine 145 | /// 146 | public void WriteLine() 147 | { 148 | _writer.WriteLine(); 149 | } 150 | 151 | /// 152 | /// Write a string value followed by a NewLine 153 | /// 154 | public void WriteLine(string value) 155 | { 156 | _writer.WriteLine(value); 157 | } 158 | 159 | /// 160 | /// Gets the encoding for this ExtendedTextWriter 161 | /// 162 | public Encoding Encoding => _writer.Encoding; 163 | 164 | #endregion 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/ColorStyle.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | namespace NUnit.Runner 25 | { 26 | /// 27 | /// ColorStyle enumerates the various styles used in the console display 28 | /// 29 | public enum ColorStyle 30 | { 31 | /// 32 | /// Color for headers 33 | /// 34 | Header, 35 | /// 36 | /// Color for sub-headers 37 | /// 38 | SubHeader, 39 | /// 40 | /// Color for each of the section headers 41 | /// 42 | SectionHeader, 43 | /// 44 | /// The default color for items that don't fit into the other categories 45 | /// 46 | Default, 47 | /// 48 | /// Test output 49 | /// 50 | Output, 51 | /// 52 | /// Color for help text 53 | /// 54 | Help, 55 | /// 56 | /// Color for labels 57 | /// 58 | Label, 59 | /// 60 | /// Color for values, usually go beside labels 61 | /// 62 | Value, 63 | /// 64 | /// Color for passed tests 65 | /// 66 | Pass, 67 | /// 68 | /// Color for failed tests 69 | /// 70 | Failure, 71 | /// 72 | /// Color for warnings, ignored or skipped tests 73 | /// 74 | Warning, 75 | /// 76 | /// Color for errors and exceptions 77 | /// 78 | Error 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/CommandLineOptions.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.Collections.Generic; 26 | using System.IO; 27 | using NUnit.Engine; 28 | using NUnit.Options; 29 | 30 | namespace NUnit.Runner 31 | { 32 | public class CommandLineOptions : OptionSet 33 | { 34 | private bool validated; 35 | private bool noresult; 36 | 37 | #region Constructor 38 | 39 | public CommandLineOptions(params string[] args) 40 | { 41 | ConfigureOptions(); 42 | if (args != null) 43 | Parse(args); 44 | } 45 | 46 | #endregion 47 | 48 | #region Properties 49 | 50 | // .Net Core runner options http://dotnet.github.io/docs/core-concepts/core-sdk/cli/dotnet-test-protocol.html 51 | public bool DesignTime { get; private set; } 52 | 53 | public int Port { get; private set; } = -1; 54 | public bool PortSpecified => Port >= 0; 55 | 56 | public bool WaitCommand { get; private set; } 57 | 58 | public bool List { get; private set; } 59 | 60 | public int ParentProcessId { get; private set; } 61 | 62 | // Action to Perform 63 | 64 | public bool Explore { get; private set; } 65 | 66 | public bool ShowHelp { get; private set; } 67 | 68 | public bool ShowVersion { get; private set; } 69 | 70 | // Select tests 71 | 72 | public IList InputFiles { get; } = new List(); 73 | 74 | public IList TestList { get; } = new List(); 75 | 76 | public string TestParameters { get; private set; } 77 | 78 | public string WhereClause { get; private set; } 79 | public bool WhereClauseSpecified => WhereClause != null; 80 | 81 | public int DefaultTimeout { get; private set; } = -1; 82 | public bool DefaultTimeoutSpecified => DefaultTimeout >= 0; 83 | 84 | public int RandomSeed { get; private set; } = -1; 85 | public bool RandomSeedSpecified => RandomSeed >= 0; 86 | 87 | public string DefaultTestNamePattern { get; private set; } 88 | 89 | #if false 90 | public int NumberOfTestWorkers { get; private set; } = -1; 91 | public bool NumberOfTestWorkersSpecified => NumberOfTestWorkers >= 0; 92 | #endif 93 | 94 | public bool StopOnError { get; private set; } 95 | 96 | public bool WaitBeforeExit { get; private set; } 97 | 98 | public bool TeamCity { get; private set; } 99 | 100 | #if NET451 101 | public bool Debug { get; private set; } 102 | #endif 103 | 104 | // Output Control 105 | 106 | public bool NoHeader { get; private set; } 107 | 108 | public bool NoColor { get; private set; } 109 | 110 | public string DisplayTestLabels { get; private set; } 111 | 112 | string workDirectory = null; 113 | public string WorkDirectory => workDirectory ?? Env.DefaultWorkDirectory; 114 | 115 | public bool WorkDirectorySpecified => workDirectory != null; 116 | 117 | public string InternalTraceLevel { get; private set; } 118 | public bool InternalTraceLevelSpecified => InternalTraceLevel != null; 119 | 120 | private List resultOutputSpecifications = new List(); 121 | public IList ResultOutputSpecifications 122 | { 123 | get 124 | { 125 | if (noresult) 126 | return new OutputSpecification[0]; 127 | 128 | if (resultOutputSpecifications.Count == 0) 129 | resultOutputSpecifications.Add(new OutputSpecification("TestResult.xml")); 130 | 131 | return resultOutputSpecifications; 132 | } 133 | } 134 | 135 | public IList ExploreOutputSpecifications { get; private set; } = new List(); 136 | 137 | // Error Processing 138 | 139 | public IList ErrorMessages { get; private set; } = new List(); 140 | 141 | #endregion 142 | 143 | #region Public Methods 144 | 145 | public bool Validate() 146 | { 147 | if (!validated) 148 | { 149 | CheckOptionCombinations(); 150 | validated = true; 151 | } 152 | return ErrorMessages.Count == 0; 153 | } 154 | 155 | #endregion 156 | 157 | #region Helper Methods 158 | 159 | void CheckOptionCombinations() 160 | { 161 | // TODO: Fill in any validations 162 | } 163 | 164 | /// 165 | /// Case is ignored when val is compared to validValues. When a match is found, the 166 | /// returned value will be in the canonical case from validValues. 167 | /// 168 | protected string RequiredValue(string val, string option, params string[] validValues) 169 | { 170 | if (string.IsNullOrEmpty(val)) 171 | ErrorMessages.Add("Missing required value for option '" + option + "'."); 172 | 173 | bool isValid = true; 174 | 175 | if (validValues != null && validValues.Length > 0) 176 | { 177 | isValid = false; 178 | 179 | foreach (string valid in validValues) 180 | if (string.Compare(valid, val, StringComparison.OrdinalIgnoreCase) == 0) 181 | return valid; 182 | 183 | } 184 | 185 | if (!isValid) 186 | ErrorMessages.Add(string.Format("The value '{0}' is not valid for option '{1}'.", val, option)); 187 | 188 | return val; 189 | } 190 | 191 | protected int RequiredInt(string val, string option) 192 | { 193 | // We have to return something even though the value will 194 | // be ignored if an error is reported. The -1 value seems 195 | // like a safe bet in case it isn't ignored due to a bug. 196 | int result = -1; 197 | 198 | if (string.IsNullOrEmpty(val)) 199 | ErrorMessages.Add("Missing required value for option '" + option + "'."); 200 | else 201 | { 202 | // NOTE: Don't replace this with TryParse or you'll break the CF build! 203 | try 204 | { 205 | result = int.Parse(val); 206 | } 207 | catch (Exception) 208 | { 209 | ErrorMessages.Add("An int value was expected for option '{0}' but a value of '{1}' was used"); 210 | } 211 | } 212 | 213 | return result; 214 | } 215 | 216 | private string ExpandToFullPath(string path) 217 | { 218 | if (path == null) return null; 219 | return Path.GetFullPath(path); 220 | } 221 | 222 | void ConfigureOptions() 223 | { 224 | // NOTE: The order in which patterns are added 225 | // determines the display order for the help. 226 | 227 | // Select Tests 228 | this.Add("test=", "Comma-separated list of {NAMES} of tests to run or explore. This option may be repeated.", 229 | v => ((List)TestList).AddRange(TestNameParser.Parse(RequiredValue(v, "--test")))); 230 | 231 | this.Add("where=", "Test selection {EXPRESSION} indicating what tests will be run. See description below.", 232 | v => WhereClause = RequiredValue(v, "--where")); 233 | 234 | this.Add("params|p=", "Define a test parameter.", 235 | v => 236 | { 237 | string parameters = RequiredValue(v, "--params"); 238 | 239 | foreach (string param in parameters.Split(new[] { ';' })) 240 | { 241 | if (!param.Contains("=")) 242 | ErrorMessages.Add("Invalid format for test parameter. Use NAME=VALUE."); 243 | } 244 | 245 | if (TestParameters == null) 246 | TestParameters = parameters; 247 | else 248 | TestParameters += ";" + parameters; 249 | }); 250 | 251 | this.Add("timeout=", "Set timeout for each test case in {MILLISECONDS}.", 252 | v => DefaultTimeout = RequiredInt(v, "--timeout")); 253 | 254 | this.Add("seed=", "Set the random {SEED} used to generate test cases.", 255 | v => RandomSeed = RequiredInt(v, "--seed")); 256 | #if false 257 | this.Add("workers=", "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.", 258 | v => numWorkers = RequiredInt(v, "--workers")); 259 | #endif 260 | this.Add("stoponerror", "Stop run immediately upon any test failure or error.", 261 | v => StopOnError = v != null); 262 | 263 | this.Add("wait", "Wait for input before closing console window.", 264 | v => WaitBeforeExit = v != null); 265 | 266 | // Output Control 267 | this.Add("work=", "{PATH} of the directory to use for output files. If not specified, defaults to the current directory.", 268 | v => workDirectory = RequiredValue(v, "--work")); 269 | 270 | this.Add("result=", "An output {SPEC} for saving the test results.\nThis option may be repeated.", 271 | v => resultOutputSpecifications.Add(new OutputSpecification(RequiredValue(v, "--resultxml")))); 272 | 273 | this.Add("explore:", "Display or save test info rather than running tests. Optionally provide an output {SPEC} for saving the test info. This option may be repeated.", v => 274 | { 275 | Explore = true; 276 | if (v != null) 277 | ExploreOutputSpecifications.Add(new OutputSpecification(v)); 278 | }); 279 | 280 | this.Add("noresult", "Don't save any test results.", 281 | v => noresult = v != null); 282 | 283 | this.Add("labels=", "Specify whether to write test case names to the output. Values: Off, On, All", 284 | v => DisplayTestLabels = RequiredValue(v, "--labels", "Off", "On", "All")); 285 | 286 | this.Add("test-name-format=", "Non-standard naming pattern to use in generating test names.", 287 | v => DefaultTestNamePattern = RequiredValue(v, "--test-name-format")); 288 | 289 | this.Add("trace=", "Set internal trace {LEVEL}.\nValues: Off, Error, Warning, Info, Verbose (Debug)", 290 | v => InternalTraceLevel = RequiredValue(v, "--trace", "Off", "Error", "Warning", "Info", "Verbose", "Debug")); 291 | 292 | this.Add("noheader|noh", "Suppress display of program information at start of run.", 293 | v => NoHeader = v != null); 294 | 295 | this.Add("nocolor|noc", "Displays console output without color.", 296 | v => NoColor = v != null); 297 | 298 | this.Add("teamcity|tc", "Enables teamcity tests processing messages.", 299 | v => TeamCity = v != null); 300 | 301 | this.Add("help|h|?", "Display this message and exit.", 302 | v => ShowHelp = v != null); 303 | 304 | this.Add("version|V", "Display the header and exit.", 305 | v => ShowVersion = v != null); 306 | 307 | #if NET451 308 | this.Add("debug", "Attaches the debugger on launch", 309 | v => Debug = v != null); 310 | #endif 311 | 312 | // .NET Core runner options 313 | this.Add("designtime", "Used to indicate that the runner is being launched by an IDE", 314 | v => DesignTime = v != null); 315 | 316 | this.Add("port=", "Used by IDEs to specify a port number to listen for a connection", 317 | v => Port = RequiredInt(v, "--port")); 318 | 319 | this.Add("wait-command", "Used by IDEs to indicate that the runner should connect to the port and wait for commands, instead of going ahead and executing the tests", 320 | v => WaitCommand = v != null); 321 | 322 | this.Add("list", "Used by IDEs to request a list of tests that can be run", 323 | v => List = v != null); 324 | 325 | this.Add("parentProcessId", "Used by IDEs to indicate the Parent PID", 326 | v => ParentProcessId = RequiredInt(v, "--parentProcessId")); 327 | 328 | // Default 329 | this.Add("<>", v => 330 | { 331 | if (v.StartsWith("-", StringComparison.Ordinal) || v.StartsWith("/", StringComparison.Ordinal) && Path.DirectorySeparatorChar != '/') 332 | ErrorMessages.Add("Invalid argument: " + v); 333 | else 334 | InputFiles.Add(v); 335 | }); 336 | } 337 | 338 | #endregion 339 | } 340 | } 341 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Env.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.IO; 26 | 27 | namespace NUnit.Runner 28 | { 29 | /// 30 | /// Env is a static class that provides some of the features of 31 | /// System.Environment that are not available under all runtimes 32 | /// 33 | public class Env 34 | { 35 | static Env() 36 | { 37 | #if NETSTANDARD1_5 || NETCOREAPP1_0 38 | DocumentFolder = "."; 39 | string drive = Environment.GetEnvironmentVariable("HOMEDRIVE"); 40 | string path = Environment.GetEnvironmentVariable("HOMEPATH"); 41 | if (drive != null && path != null) 42 | { 43 | DocumentFolder = Path.Combine(drive, path, "documents"); 44 | } 45 | else if (path != null) 46 | { 47 | DocumentFolder = Path.Combine(path, "documents"); 48 | } 49 | else 50 | { 51 | string profile = Environment.GetEnvironmentVariable("USERPROFILE"); 52 | if (profile != null) 53 | DocumentFolder = Path.Combine(profile, "documents"); 54 | } 55 | DefaultWorkDirectory = Directory.GetCurrentDirectory(); 56 | #else 57 | DocumentFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal); 58 | DefaultWorkDirectory = Environment.CurrentDirectory; 59 | #endif 60 | } 61 | 62 | /// 63 | /// Path to the 'My Documents' folder 64 | /// 65 | public static string DocumentFolder; 66 | 67 | /// 68 | /// Directory used for file output if not specified on commandline. 69 | /// 70 | public static readonly string DefaultWorkDirectory; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Extensions/SafeAttributeAccess.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System.Xml; 25 | 26 | namespace NUnit.Engine.Listeners 27 | { 28 | /// 29 | /// SafeAttributeAccess provides an extension method for accessing XML attributes. 30 | /// 31 | public static class SafeAttributeAccess 32 | { 33 | /// 34 | /// Gets the value of the given attribute. 35 | /// 36 | /// The result. 37 | /// The name. 38 | /// 39 | public static string GetAttribute(this XmlNode result, string name) 40 | { 41 | XmlAttribute attr = result.Attributes[name]; 42 | 43 | return attr == null ? null : attr.Value; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Extensions/ServiceMessage.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2015 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | namespace NUnit.Engine.Listeners 25 | { 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Collections.ObjectModel; 29 | 30 | internal struct ServiceMessage 31 | { 32 | public ServiceMessage(string name, params ServiceMessageAttr[] attributes) 33 | : this() 34 | { 35 | // ReSharper disable once UseNameofExpression 36 | if (name == null) throw new ArgumentNullException("name"); 37 | // ReSharper disable once UseNameofExpression 38 | if (attributes == null) throw new ArgumentNullException("attributes"); 39 | 40 | Name = name; 41 | Attributes = new ReadOnlyCollection(attributes); 42 | } 43 | 44 | public string Name { get; private set; } 45 | 46 | public IEnumerable Attributes { get; private set; } 47 | 48 | public static class Names 49 | { 50 | public const string TestStdOut = "testStdOut"; 51 | public const string TestSuiteStarted = "testSuiteStarted"; 52 | public const string TestSuiteFinished = "testSuiteFinished"; 53 | public const string FlowStarted = "flowStarted"; 54 | public const string FlowFinished = "flowFinished"; 55 | public const string TestStarted = "testStarted"; 56 | public const string TestFinished = "testFinished"; 57 | public const string TestFailed = "testFailed"; 58 | public const string TestIgnored = "testIgnored"; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Extensions/ServiceMessageAttr.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2015 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | namespace NUnit.Engine.Listeners 25 | { 26 | using System; 27 | using System.Diagnostics.CodeAnalysis; 28 | 29 | [SuppressMessage("ReSharper", "UseNameofExpression")] 30 | internal struct ServiceMessageAttr 31 | { 32 | public ServiceMessageAttr(string name, string value) 33 | : this() 34 | { 35 | if (name == null) throw new ArgumentNullException("name"); 36 | if (value == null) throw new ArgumentNullException("value"); 37 | 38 | Name = name; 39 | Value = value; 40 | } 41 | 42 | public string Value { get; private set; } 43 | 44 | public string Name { get; private set; } 45 | 46 | public static class Names 47 | { 48 | public const string Name = "name"; 49 | public const string FlowId = "flowId"; 50 | public const string Message = "message"; 51 | public const string Out = "out"; 52 | public const string TcTags = "tc:tags"; 53 | public const string Parent = "parent"; 54 | public const string CaptureStandardOutput = "captureStandardOutput"; 55 | public const string Duration = "duration"; 56 | public const string Details = "details"; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Extensions/ServiceMessageWriter.cs: -------------------------------------------------------------------------------- 1 | namespace NUnit.Engine.Listeners 2 | { 3 | using System; 4 | using System.Diagnostics.CodeAnalysis; 5 | using System.Globalization; 6 | using System.IO; 7 | 8 | [SuppressMessage("ReSharper", "UseNameofExpression")] 9 | internal class ServiceMessageWriter 10 | { 11 | private const string Header = "##teamcity["; 12 | private const string Footer = "]"; 13 | 14 | public void Write(TextWriter writer, ServiceMessage serviceMessage) 15 | { 16 | if (writer == null) throw new ArgumentNullException("writer"); 17 | 18 | writer.Write(Header); 19 | writer.Write(serviceMessage.Name); 20 | foreach (var attribute in serviceMessage.Attributes) 21 | { 22 | writer.Write(' '); 23 | Write(writer, attribute); 24 | } 25 | 26 | writer.Write(Footer); 27 | } 28 | 29 | 30 | private void Write(TextWriter writer, ServiceMessageAttr attribute) 31 | { 32 | writer.Write(attribute.Name); 33 | writer.Write("='"); 34 | writer.Write(EscapeString(attribute.Value)); 35 | writer.Write('\''); 36 | } 37 | 38 | private static string EscapeString(string value) 39 | { 40 | return value != null 41 | ? value.Replace("|", "||") 42 | .Replace("'", "|'") 43 | .Replace("\n", "|n") 44 | .Replace("\r", "|r") 45 | .Replace(char.ConvertFromUtf32(int.Parse("0086", NumberStyles.HexNumber)), "|x") 46 | .Replace(char.ConvertFromUtf32(int.Parse("2028", NumberStyles.HexNumber)), "|l") 47 | .Replace(char.ConvertFromUtf32(int.Parse("2029", NumberStyles.HexNumber)), "|p") 48 | .Replace("[", "|[") 49 | .Replace("]", "|]") 50 | : null; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Extensions/TeamCityEventListener.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2015 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.IO; 26 | using System.Xml; 27 | using System.Collections.Generic; 28 | using System.Globalization; 29 | 30 | namespace NUnit.Engine.Listeners 31 | { 32 | using System.Diagnostics.CodeAnalysis; 33 | using System.Text; 34 | 35 | // Note: Setting mimimum engine version in this case is 36 | // purely documentary since engines prior to 3.4 do not 37 | // check the EngineVersion property and will try to 38 | // load this extension anyway. 39 | [SuppressMessage("ReSharper", "UseNameofExpression")] 40 | public class TeamCityEventListener 41 | { 42 | private static readonly ServiceMessageWriter ServiceMessageWriter = new ServiceMessageWriter(); 43 | private readonly TextWriter _outWriter; 44 | private readonly Dictionary _refs = new Dictionary(); 45 | private readonly Dictionary _blockCounters = new Dictionary(); 46 | 47 | public TeamCityEventListener() : this(Console.Out) { } 48 | 49 | public TeamCityEventListener(TextWriter outWriter) 50 | { 51 | if (outWriter == null) throw new ArgumentNullException("outWriter"); 52 | 53 | _outWriter = outWriter; 54 | } 55 | 56 | #region ITestEventListener Implementation 57 | 58 | public void OnTestEvent(string report) 59 | { 60 | var doc = new XmlDocument(); 61 | doc.LoadXml(report); 62 | 63 | var testEvent = doc.FirstChild; 64 | RegisterMessage(testEvent); 65 | } 66 | 67 | #endregion 68 | 69 | public void RegisterMessage(XmlNode testEvent) 70 | { 71 | if (testEvent == null) throw new ArgumentNullException("testEvent"); 72 | 73 | var messageName = testEvent.Name; 74 | if (string.IsNullOrEmpty(messageName)) 75 | { 76 | return; 77 | } 78 | 79 | messageName = messageName.ToLowerInvariant(); 80 | if (messageName == "start-run") 81 | { 82 | _refs.Clear(); 83 | return; 84 | } 85 | 86 | var fullName = testEvent.GetAttribute("fullname"); 87 | if (string.IsNullOrEmpty(fullName)) 88 | { 89 | return; 90 | } 91 | 92 | var id = testEvent.GetAttribute("id"); 93 | if (id == null) 94 | { 95 | id = string.Empty; 96 | } 97 | 98 | var parentId = testEvent.GetAttribute("parentId"); 99 | var flowId = "."; 100 | if (parentId != null) 101 | { 102 | // NUnit 3 case 103 | string rootId; 104 | flowId = TryFindRootId(parentId, out rootId) ? rootId : id; 105 | } 106 | else 107 | { 108 | // NUnit 2 case 109 | if (!string.IsNullOrEmpty(id)) 110 | { 111 | var idParts = id.Split('-'); 112 | if (idParts.Length == 2) 113 | { 114 | flowId = idParts[0]; 115 | } 116 | } 117 | } 118 | 119 | string testFlowId; 120 | if (id != flowId && parentId != null) 121 | { 122 | testFlowId = id; 123 | } 124 | else 125 | { 126 | testFlowId = flowId; 127 | if (testFlowId == null) 128 | { 129 | testFlowId = id; 130 | } 131 | } 132 | 133 | switch (messageName.ToLowerInvariant()) 134 | { 135 | case "start-suite": 136 | _refs[id] = parentId; 137 | StartSuiteCase(parentId, flowId, fullName); 138 | break; 139 | 140 | case "test-suite": 141 | _refs.Remove(id); 142 | TestSuiteCase(parentId, flowId, fullName); 143 | break; 144 | 145 | case "start-test": 146 | _refs[id] = parentId; 147 | CaseStartTest(id, flowId, parentId, testFlowId, fullName); 148 | break; 149 | 150 | case "test-case": 151 | try 152 | { 153 | if (!_refs.Remove(id)) 154 | { 155 | // When test without starting 156 | CaseStartTest(id, flowId, parentId, testFlowId, fullName); 157 | } 158 | 159 | var result = testEvent.GetAttribute("result"); 160 | if (string.IsNullOrEmpty(result)) 161 | { 162 | break; 163 | } 164 | 165 | switch (result.ToLowerInvariant()) 166 | { 167 | case "passed": 168 | OnTestFinished(testFlowId, testEvent, fullName); 169 | break; 170 | 171 | case "inconclusive": 172 | OnTestInconclusive(testFlowId, testEvent, fullName); 173 | break; 174 | 175 | case "skipped": 176 | OnTestSkipped(testFlowId, testEvent, fullName); 177 | break; 178 | 179 | case "failed": 180 | OnTestFailed(testFlowId, testEvent, fullName); 181 | break; 182 | } 183 | } 184 | finally 185 | { 186 | if (id != flowId && parentId != null) 187 | { 188 | OnFlowFinished(id); 189 | } 190 | } 191 | 192 | break; 193 | } 194 | } 195 | 196 | private void CaseStartTest(string id, string flowId, string parentId, string testFlowId, string fullName) 197 | { 198 | if (id != flowId && parentId != null) 199 | { 200 | OnFlowStarted(id, flowId); 201 | } 202 | 203 | OnTestStart(testFlowId, fullName); 204 | } 205 | 206 | private void TestSuiteCase(string parentId, string flowId, string fullName) 207 | { 208 | // NUnit 3 case 209 | if (parentId == string.Empty) 210 | { 211 | OnRootSuiteFinish(flowId, fullName); 212 | } 213 | 214 | // NUnit 2 case 215 | if (parentId == null) 216 | { 217 | if (ChangeBlockCounter(flowId, -1) == 0) 218 | { 219 | OnRootSuiteFinish(flowId, fullName); 220 | } 221 | } 222 | } 223 | 224 | private void StartSuiteCase(string parentId, string flowId, string fullName) 225 | { 226 | // NUnit 3 case 227 | if (parentId == string.Empty) 228 | { 229 | OnRootSuiteStart(flowId, fullName); 230 | } 231 | 232 | // NUnit 2 case 233 | if (parentId == null) 234 | { 235 | if (ChangeBlockCounter(flowId, 1) == 1) 236 | { 237 | OnRootSuiteStart(flowId, fullName); 238 | } 239 | } 240 | } 241 | 242 | private int ChangeBlockCounter(string flowId, int changeValue) 243 | { 244 | int currentBlockCounter; 245 | if (!_blockCounters.TryGetValue(flowId, out currentBlockCounter)) 246 | { 247 | currentBlockCounter = 0; 248 | } 249 | 250 | currentBlockCounter += changeValue; 251 | _blockCounters[flowId] = currentBlockCounter; 252 | return currentBlockCounter; 253 | } 254 | 255 | private bool TryFindParentId(string id, out string parentId) 256 | { 257 | if (id == null) 258 | { 259 | throw new ArgumentNullException("id"); 260 | } 261 | 262 | return _refs.TryGetValue(id, out parentId) && !string.IsNullOrEmpty(parentId); 263 | } 264 | 265 | private bool TryFindRootId(string id, out string rootId) 266 | { 267 | if (id == null) 268 | { 269 | throw new ArgumentNullException("id"); 270 | } 271 | 272 | while (TryFindParentId(id, out rootId) && id != rootId) 273 | { 274 | id = rootId; 275 | } 276 | 277 | rootId = id; 278 | return !string.IsNullOrEmpty(id); 279 | } 280 | 281 | private void TrySendOutput(string flowId, XmlNode message, string fullName) 282 | { 283 | if (message == null) throw new ArgumentNullException("message"); 284 | 285 | var output = message.SelectSingleNode("output"); 286 | if (output == null) 287 | { 288 | return; 289 | } 290 | 291 | SendOutput(flowId, fullName, output.InnerText); 292 | } 293 | 294 | private void TrySendReasonMessage(string flowId, XmlNode message, string fullName) 295 | { 296 | if (message == null) throw new ArgumentNullException("message"); 297 | 298 | var reasonMessageElement = message.SelectSingleNode("reason/message"); 299 | if (reasonMessageElement == null) 300 | { 301 | return; 302 | } 303 | 304 | var reasonMessage = reasonMessageElement.InnerText; 305 | if (string.IsNullOrEmpty(reasonMessage)) 306 | { 307 | return; 308 | } 309 | 310 | SendOutput(flowId, fullName, "Assert.Pass message: " + reasonMessage); 311 | } 312 | 313 | private void SendOutput(string flowId, string fullName, string outputStr) 314 | { 315 | if (string.IsNullOrEmpty(outputStr)) 316 | { 317 | return; 318 | } 319 | 320 | Write(new ServiceMessage(ServiceMessage.Names.TestStdOut, 321 | new ServiceMessageAttr(ServiceMessageAttr.Names.Name, fullName), 322 | new ServiceMessageAttr(ServiceMessageAttr.Names.Out, outputStr), 323 | new ServiceMessageAttr(ServiceMessageAttr.Names.FlowId, flowId), 324 | new ServiceMessageAttr(ServiceMessageAttr.Names.TcTags, "tc:parseServiceMessagesInside"))); 325 | } 326 | 327 | private void OnRootSuiteStart(string flowId, string assemblyName) 328 | { 329 | assemblyName = Path.GetFileName(assemblyName); 330 | 331 | Write(new ServiceMessage(ServiceMessage.Names.TestSuiteStarted, 332 | new ServiceMessageAttr(ServiceMessageAttr.Names.Name, assemblyName), 333 | new ServiceMessageAttr(ServiceMessageAttr.Names.FlowId, flowId))); 334 | } 335 | 336 | private void OnRootSuiteFinish(string flowId, string assemblyName) 337 | { 338 | assemblyName = Path.GetFileName(assemblyName); 339 | 340 | Write(new ServiceMessage(ServiceMessage.Names.TestSuiteFinished, 341 | new ServiceMessageAttr(ServiceMessageAttr.Names.Name, assemblyName), 342 | new ServiceMessageAttr(ServiceMessageAttr.Names.FlowId, flowId))); 343 | } 344 | 345 | private void OnFlowStarted(string flowId, string parentFlowId) 346 | { 347 | Write(new ServiceMessage(ServiceMessage.Names.FlowStarted, 348 | new ServiceMessageAttr(ServiceMessageAttr.Names.FlowId, flowId), 349 | new ServiceMessageAttr(ServiceMessageAttr.Names.Parent, parentFlowId))); 350 | } 351 | 352 | private void OnFlowFinished(string flowId) 353 | { 354 | Write(new ServiceMessage(ServiceMessage.Names.FlowFinished, 355 | new ServiceMessageAttr(ServiceMessageAttr.Names.FlowId, flowId))); 356 | } 357 | 358 | private void OnTestStart(string flowId, string fullName) 359 | { 360 | Write(new ServiceMessage(ServiceMessage.Names.TestStarted, 361 | new ServiceMessageAttr(ServiceMessageAttr.Names.Name, fullName), 362 | new ServiceMessageAttr(ServiceMessageAttr.Names.CaptureStandardOutput, "false"), 363 | new ServiceMessageAttr(ServiceMessageAttr.Names.FlowId, flowId))); 364 | } 365 | 366 | private void OnTestFinished(string flowId, XmlNode message, string fullName) 367 | { 368 | if (message == null) 369 | { 370 | throw new ArgumentNullException("message"); 371 | } 372 | 373 | var durationStr = message.GetAttribute(ServiceMessageAttr.Names.Duration); 374 | double durationDecimal; 375 | int durationMilliseconds = 0; 376 | if (durationStr != null && double.TryParse(durationStr, NumberStyles.Any, CultureInfo.InvariantCulture, out durationDecimal)) 377 | { 378 | durationMilliseconds = (int)(durationDecimal * 1000d); 379 | } 380 | 381 | TrySendOutput(flowId, message, fullName); 382 | TrySendReasonMessage(flowId, message, fullName); 383 | 384 | Write(new ServiceMessage(ServiceMessage.Names.TestFinished, 385 | new ServiceMessageAttr(ServiceMessageAttr.Names.Name, fullName), 386 | new ServiceMessageAttr(ServiceMessageAttr.Names.Duration, durationMilliseconds.ToString()), 387 | new ServiceMessageAttr(ServiceMessageAttr.Names.FlowId, flowId))); 388 | } 389 | 390 | private void OnTestFailed(string flowId, XmlNode message, string fullName) 391 | { 392 | if (message == null) 393 | { 394 | throw new ArgumentNullException("message"); 395 | } 396 | 397 | var errorMessage = message.SelectSingleNode("failure/message"); 398 | var stackTrace = message.SelectSingleNode("failure/stack-trace"); 399 | 400 | Write(new ServiceMessage(ServiceMessage.Names.TestFailed, 401 | new ServiceMessageAttr(ServiceMessageAttr.Names.Name, fullName), 402 | new ServiceMessageAttr(ServiceMessageAttr.Names.Message, errorMessage == null ? string.Empty : errorMessage.InnerText), 403 | new ServiceMessageAttr(ServiceMessageAttr.Names.Details, stackTrace == null ? string.Empty : stackTrace.InnerText), 404 | new ServiceMessageAttr(ServiceMessageAttr.Names.FlowId, flowId))); 405 | 406 | OnTestFinished(flowId, message, fullName); 407 | } 408 | 409 | private void OnTestSkipped(string flowId, XmlNode message, string fullName) 410 | { 411 | if (message == null) 412 | { 413 | throw new ArgumentNullException("message"); 414 | } 415 | 416 | TrySendOutput(flowId, message, fullName); 417 | var reason = message.SelectSingleNode("reason/message"); 418 | 419 | Write(new ServiceMessage(ServiceMessage.Names.TestIgnored, 420 | new ServiceMessageAttr(ServiceMessageAttr.Names.Name, fullName), 421 | new ServiceMessageAttr(ServiceMessageAttr.Names.Message, reason == null ? string.Empty : reason.InnerText), 422 | new ServiceMessageAttr(ServiceMessageAttr.Names.FlowId, flowId))); 423 | } 424 | 425 | private void OnTestInconclusive(string flowId, XmlNode message, string fullName) 426 | { 427 | if (message == null) 428 | { 429 | throw new ArgumentNullException("message"); 430 | } 431 | 432 | TrySendOutput(flowId, message, fullName); 433 | 434 | Write(new ServiceMessage(ServiceMessage.Names.TestIgnored, 435 | new ServiceMessageAttr(ServiceMessageAttr.Names.Name, fullName), 436 | new ServiceMessageAttr(ServiceMessageAttr.Names.Message, "Inconclusive"), 437 | new ServiceMessageAttr(ServiceMessageAttr.Names.FlowId, flowId))); 438 | } 439 | 440 | private void Write(ServiceMessage serviceMessage) 441 | { 442 | var sb = new StringBuilder(); 443 | using (var writer = new StringWriter(sb)) 444 | { 445 | ServiceMessageWriter.Write(writer, serviceMessage); 446 | } 447 | 448 | _outWriter.WriteLine(sb.ToString()); 449 | } 450 | } 451 | } 452 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Extensions/TestExtensions.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.Globalization; 26 | using System.Linq; 27 | using System.Security.Cryptography; 28 | using System.Text; 29 | using System.Xml.Linq; 30 | using Microsoft.Extensions.Testing.Abstractions; 31 | 32 | namespace NUnit.Runner.Extensions 33 | { 34 | /// 35 | /// Converts between the Microsoft.Testing.Abstractions classes and the 36 | /// equivilent NUnit xml 37 | /// 38 | public static class TestExtensions 39 | { 40 | const double MIN_DURATION = 0.001d; 41 | 42 | static SHA1 SHA { get; } = SHA1.Create(); 43 | 44 | /// 45 | /// Takes a string, signs it with a SHA1 algorithm and converts the 46 | /// resulting hash to a 47 | /// 48 | /// 49 | /// 50 | /// The SHA1 hash algorithm results in a 140 bit digest, but a 51 | /// Guid only stores 128 bits. Therefore, we are tossing out 52 | /// the last 12 bits of the SHA1 hash in order to convert the 53 | /// result to a Guid. 54 | /// 55 | /// 56 | /// 57 | /// 58 | public static Guid GetSignatureAsGuid(this string attribute) 59 | { 60 | var hash = SHA.ComputeHash(Encoding.Unicode.GetBytes(attribute)); 61 | var b = new byte[16]; 62 | Array.Copy(hash, b, 16); 63 | return new Guid(b); 64 | } 65 | 66 | /// 67 | /// Takes an NUnit id attribute and converts it to a Guid Id 68 | /// 69 | /// 70 | /// 71 | public static Guid ConvertToGuid(this XAttribute attribute) 72 | { 73 | if (attribute == null) 74 | return Guid.Empty; 75 | 76 | var hash = SHA.ComputeHash(Encoding.UTF8.GetBytes(attribute.Value)); 77 | var guid = new byte[16]; 78 | Array.Copy(hash, guid, 16); 79 | return new Guid(guid); 80 | } 81 | 82 | public static DateTimeOffset ConvertToDateTime(this XAttribute attribute) 83 | { 84 | var result = DateTimeOffset.UtcNow; 85 | 86 | if (attribute != null) 87 | DateTimeOffset.TryParse(attribute.Value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out result); 88 | 89 | return result; 90 | } 91 | 92 | /// 93 | /// Converts an NUnit XML duration in seconds into a TimeSpan 94 | /// 95 | /// 96 | /// 97 | public static TimeSpan ConvertToTimeSpan(this XAttribute attribute, TestOutcome outcome) 98 | { 99 | double duration = MIN_DURATION; // Some runners cannot handle a duration of 0 100 | 101 | if (outcome == TestOutcome.Skipped) 102 | return TimeSpan.FromTicks(1); 103 | 104 | if (attribute != null) 105 | double.TryParse(attribute.Value, out duration); 106 | 107 | return TimeSpan.FromSeconds(Math.Max(duration, MIN_DURATION)); 108 | } 109 | 110 | public static TestOutcome ConvertToTestOutcome(this XAttribute attribute) 111 | { 112 | if (attribute == null) 113 | return TestOutcome.None; 114 | 115 | if(attribute.Value.StartsWith("Passed", StringComparison.Ordinal)) 116 | return TestOutcome.Passed; 117 | if (attribute.Value.StartsWith("Failed", StringComparison.Ordinal)) 118 | return TestOutcome.Failed; 119 | if (attribute.Value.StartsWith("Skipped", StringComparison.Ordinal)) 120 | return TestOutcome.Skipped; 121 | if (attribute.Value.StartsWith("Inconclusive", StringComparison.Ordinal)) 122 | return TestOutcome.Skipped; 123 | 124 | return TestOutcome.None; 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Interfaces/ITestListener.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | namespace NUnit.Runner.Interfaces 25 | { 26 | public interface ITestListener 27 | { 28 | void OnTestEvent(string xml); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Navigation/NavigationDataProvider.cs: -------------------------------------------------------------------------------- 1 | // **************************************************************** 2 | // Copyright (c) 2016 NUnit Software. All rights reserved. 3 | // **************************************************************** 4 | 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | using Microsoft.DotNet.ProjectModel; 9 | using Microsoft.Extensions.Testing.Abstractions; 10 | 11 | namespace NUnit.Runner.Navigation 12 | { 13 | public class NavigationDataProvider 14 | { 15 | public static NavigationDataProvider GetNavigationDataProvider(string assemblyPath) 16 | { 17 | var directory = Path.GetDirectoryName(assemblyPath); 18 | var assembly = Path.GetFileNameWithoutExtension(assemblyPath); 19 | var pdbPath = Path.Combine(directory, assembly + FileNameSuffixes.DotNet.ProgramDatabase); 20 | 21 | if (!File.Exists(pdbPath)) return null; 22 | 23 | return new NavigationDataProvider(assemblyPath, pdbPath); 24 | } 25 | 26 | ISourceInformationProvider _provider; 27 | Assembly _assembly; 28 | 29 | NavigationDataProvider(string assembyPath, string pdbPath) 30 | : this(assembyPath, new SourceInformationProvider(pdbPath)) 31 | { 32 | } 33 | 34 | NavigationDataProvider(string assemblyPath, ISourceInformationProvider provider) 35 | { 36 | _assembly = LoadAssembly(assemblyPath); 37 | _provider = provider; 38 | } 39 | 40 | public SourceInformation GetSourceData(string className, string methodName) 41 | { 42 | var type = _assembly.DefinedTypes.FirstOrDefault(t => t.FullName == className); 43 | var method = type?.DeclaredMethods.FirstOrDefault(m => m.Name == methodName); 44 | if (method == null) return null; 45 | 46 | return _provider.GetSourceInformation(method); 47 | } 48 | 49 | static Assembly LoadAssembly(string assemblyPath) 50 | { 51 | #if NET451 52 | return Assembly.LoadFrom(assemblyPath); 53 | #else 54 | var assembyName = Path.GetFileNameWithoutExtension(assemblyPath); 55 | return Assembly.Load(new AssemblyName(assembyName)); 56 | // I think dotnet/coreclr#5060 is causing the following to fail because of . in the name? 57 | //return System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath); 58 | #endif 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Program.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | 26 | namespace NUnit.Runner 27 | { 28 | public class Program 29 | { 30 | public static int Main(string[] args) 31 | { 32 | using (var testRunner = new TestRunner()) 33 | return testRunner.Run(args); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyCompany("NUnit Software")] 9 | [assembly: AssemblyProduct("dotnet_test_nunit")] 10 | [assembly: AssemblyCopyright("Copyright (C) 2016 NUnit Project")] 11 | [assembly: AssemblyTrademark("NUnit is a trademark of NUnit Software")] 12 | 13 | #if DEBUG 14 | [assembly: AssemblyConfiguration("Debug")] 15 | #else 16 | [assembly: AssemblyConfiguration("")] 17 | #endif 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/ResultReporter.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System.Globalization; 25 | using System.Linq; 26 | using System.Xml.Linq; 27 | using NUnit.Engine; 28 | 29 | namespace NUnit.Runner 30 | { 31 | public class ResultReporter 32 | { 33 | ColorConsoleWriter _writer; 34 | CommandLineOptions _options; 35 | XElement _result; 36 | int _reportIndex = 0; 37 | string _overallResult; 38 | 39 | public ResultReporter(ResultSummary summary, ColorConsoleWriter writer, CommandLineOptions options) 40 | { 41 | _writer = writer; 42 | _options = options; 43 | 44 | Summary = summary; 45 | 46 | TestResults = Summary.GetTestResults(); 47 | 48 | _result = TestResults.FirstNode as XElement; 49 | 50 | _overallResult = Summary.Result; 51 | if (_overallResult == "Skipped") 52 | _overallResult = "Warning"; 53 | } 54 | 55 | public ResultSummary Summary { get; } 56 | 57 | public XDocument TestResults { get; } 58 | 59 | /// 60 | /// Reports the results to the console 61 | /// 62 | public void ReportResults() 63 | { 64 | _writer.WriteLine(); 65 | 66 | if (Summary.ExplicitCount + Summary.SkipCount + Summary.IgnoreCount > 0) 67 | WriteNotRunReport(); 68 | 69 | if (_overallResult == "Failed") 70 | WriteErrorsAndFailuresReport(); 71 | 72 | WriteRunSettingsReport(); 73 | 74 | WriteSummaryReport(); 75 | } 76 | 77 | #region Summary Report 78 | 79 | public void WriteRunSettingsReport() 80 | { 81 | var firstSuite = _result.Element("test-suite"); 82 | if (firstSuite != null) 83 | { 84 | var settings = firstSuite.Element("settings")?.Elements("setting"); 85 | 86 | if (settings != null && settings.Count() > 0) 87 | { 88 | _writer.WriteLine(ColorStyle.SectionHeader, "Run Settings"); 89 | 90 | foreach (XElement node in settings) 91 | { 92 | string name = node.Attribute("name")?.Value; 93 | string val = node.Attribute("value")?.Value; 94 | _writer.WriteLabelLine($" {name}: ", val); 95 | } 96 | _writer.WriteLine(); 97 | } 98 | } 99 | } 100 | 101 | public void WriteSummaryReport() 102 | { 103 | ColorStyle overall = _overallResult == "Passed" 104 | ? ColorStyle.Pass 105 | : _overallResult == "Failed" 106 | ? ColorStyle.Failure 107 | : _overallResult == "Warning" 108 | ? ColorStyle.Warning 109 | : ColorStyle.Output; 110 | 111 | _writer.WriteLine(ColorStyle.SectionHeader, "Test Run Summary"); 112 | _writer.WriteLabelLine(" Overall result: ", _overallResult, overall); 113 | 114 | WriteSummaryCount(" Test Count: ", Summary.TestCount); 115 | WriteSummaryCount(", Passed: ", Summary.PassCount); 116 | WriteSummaryCount(", Failed: ", Summary.FailedCount, ColorStyle.Failure); 117 | WriteSummaryCount(", Inconclusive: ", Summary.InconclusiveCount); 118 | WriteSummaryCount(", Skipped: ", Summary.TotalSkipCount); 119 | _writer.WriteLine(); 120 | 121 | if (Summary.FailedCount > 0) 122 | { 123 | WriteSummaryCount(" Failed Tests - Failures: ", Summary.FailureCount); 124 | WriteSummaryCount(", Errors: ", Summary.ErrorCount, ColorStyle.Error); 125 | WriteSummaryCount(", Invalid: ", Summary.InvalidCount); 126 | _writer.WriteLine(); 127 | } 128 | if (Summary.TotalSkipCount > 0) 129 | { 130 | WriteSummaryCount(" Skipped Tests - Ignored: ", Summary.IgnoreCount); 131 | WriteSummaryCount(", Explicit: ", Summary.ExplicitCount); 132 | WriteSummaryCount(", Other: ", Summary.SkipCount); 133 | _writer.WriteLine(); 134 | } 135 | 136 | _writer.WriteLabelLine(" Start time: ", Summary.StartTime.ToString("u")); 137 | _writer.WriteLabelLine(" End time: ", Summary.EndTime.ToString("u")); 138 | _writer.WriteLabelLine(" Duration: ", $"{Summary.Duration.ToString("0.000")} seconds"); 139 | _writer.WriteLine(); 140 | } 141 | 142 | #endregion 143 | 144 | #region Errors and Failures Report 145 | 146 | public void WriteErrorsAndFailuresReport() 147 | { 148 | _reportIndex = 0; 149 | _writer.WriteLine(ColorStyle.SectionHeader, "Errors and Failures"); 150 | _writer.WriteLine(); 151 | WriteErrorsAndFailures(_result); 152 | 153 | if (_options.StopOnError) 154 | { 155 | _writer.WriteLine(ColorStyle.Failure, "Execution terminated after first error"); 156 | _writer.WriteLine(); 157 | } 158 | } 159 | 160 | void WriteErrorsAndFailures(XElement result) 161 | { 162 | string resultState = result.Attribute("result")?.Value; 163 | 164 | switch (result.Name?.ToString()) 165 | { 166 | case "test-case": 167 | if (resultState == "Failed") 168 | WriteSingleResult(result, ColorStyle.Failure); 169 | return; 170 | 171 | case "test-run": 172 | foreach (XElement childResult in result.Elements()) 173 | WriteErrorsAndFailures(childResult); 174 | break; 175 | 176 | case "test-suite": 177 | if (resultState == "Failed") 178 | { 179 | if (result.Attribute("type")?.Value == "Theory") 180 | { 181 | WriteSingleResult(result, ColorStyle.Failure); 182 | } 183 | else 184 | { 185 | var site = result.Attribute("site")?.Value; 186 | if (site != "Parent" && site != "Child") 187 | WriteSingleResult(result, ColorStyle.Failure); 188 | if (site == "SetUp") return; 189 | } 190 | } 191 | 192 | foreach (XElement childResult in result.Elements()) 193 | WriteErrorsAndFailures(childResult); 194 | 195 | break; 196 | } 197 | } 198 | 199 | #endregion 200 | 201 | #region Not Run Report 202 | 203 | public void WriteNotRunReport() 204 | { 205 | _reportIndex = 0; 206 | _writer.WriteLine(ColorStyle.SectionHeader, "Tests Not Run"); 207 | _writer.WriteLine(); 208 | WriteNotRunResults(_result); 209 | } 210 | 211 | void WriteNotRunResults(XElement result) 212 | { 213 | switch (result.Name?.ToString()) 214 | { 215 | case "test-case": 216 | string status = result.Attribute("result")?.Value; 217 | 218 | if (status == "Skipped") 219 | { 220 | string label = result.Attribute("label")?.Value; 221 | 222 | var colorStyle = label == "Ignored" 223 | ? ColorStyle.Warning 224 | : ColorStyle.Output; 225 | 226 | WriteSingleResult(result, colorStyle); 227 | } 228 | break; 229 | 230 | case "test-suite": 231 | case "test-run": 232 | foreach (XElement childResult in result.Elements()) 233 | WriteNotRunResults(childResult); 234 | 235 | break; 236 | } 237 | } 238 | 239 | #endregion 240 | 241 | #region Helper Methods 242 | 243 | void WriteSummaryCount(string label, int count) 244 | { 245 | _writer.WriteLabel(label, count.ToString(CultureInfo.CurrentUICulture)); 246 | } 247 | 248 | void WriteSummaryCount(string label, int count, ColorStyle color) 249 | { 250 | _writer.WriteLabel(label, count.ToString(CultureInfo.CurrentUICulture), count > 0 ? color : ColorStyle.Value); 251 | } 252 | 253 | static readonly char[] EOL_CHARS = { '\r', '\n' }; 254 | 255 | void WriteSingleResult(XElement result, ColorStyle colorStyle) 256 | { 257 | string status = result.Attribute("label")?.Value; 258 | if (status == null) 259 | status = result.Attribute("result")?.Value; 260 | 261 | if (status == "Failed" || status == "Error") 262 | { 263 | var site = result.Attribute("site")?.Value; 264 | if (site == "SetUp" || site == "TearDown") 265 | status = site + " " + status; 266 | } 267 | 268 | string fullName = result.Attribute("fullname")?.Value; 269 | 270 | _writer.WriteLine(colorStyle, $"{++_reportIndex}) {status} : {fullName}"); 271 | 272 | XElement failureNode = result.Element("failure"); 273 | if (failureNode != null) 274 | { 275 | string message = failureNode.Element("message")?.Value; 276 | string stacktrace = failureNode.Element("stack-trace")?.Value; 277 | 278 | // In order to control the format, we trim any line-end chars 279 | // from end of the strings we write and supply them via calls 280 | // to WriteLine(). Newlines within the strings are retained. 281 | 282 | if (message != null) 283 | _writer.WriteLine(colorStyle, message.TrimEnd(EOL_CHARS)); 284 | 285 | if (stacktrace != null) 286 | _writer.WriteLine(colorStyle, stacktrace.TrimEnd(EOL_CHARS)); 287 | } 288 | 289 | XElement reasonNode = result.Element("reason"); 290 | if (reasonNode != null) 291 | { 292 | string message = reasonNode.Element("message")?.Value; 293 | 294 | if (message != null) 295 | _writer.WriteLine(colorStyle, message.TrimEnd(EOL_CHARS)); 296 | } 297 | 298 | _writer.WriteLine(); // Skip after each item 299 | } 300 | 301 | #endregion 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/ReturnCodes.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | namespace NUnit.Runner 25 | { 26 | class ReturnCodes 27 | { 28 | #region Console Runner Return Codes 29 | 30 | public static readonly int OK = 0; 31 | public static readonly int INVALID_ARG = -1; 32 | public static readonly int INVALID_ASSEMBLY = -2; 33 | public static readonly int INVALID_TEST_FIXTURE = -4; 34 | public static readonly int UNEXPECTED_ERROR = -100; 35 | 36 | #endregion 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Sinks/Messages.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | namespace NUnit.Runner.Sinks 25 | { 26 | /// 27 | /// Defines for messages 28 | /// 29 | public static class Messages 30 | { 31 | // ITestSink 32 | public const string TestCompleted = "TestRunner.TestCompleted"; 33 | public const string WaitingCommand = "TestRunner.WaitingCommand"; 34 | 35 | // ITestDiscoverySink 36 | public const string TestFound = "TestDiscovery.TestFound"; 37 | 38 | // ITestExecutionSink 39 | public const string TestStarted = "TestExecution.TestStarted"; 40 | public const string TestResult = "TestExecution.TestResult"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Sinks/RemoteTestDiscoverySink.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.IO; 26 | using Microsoft.Extensions.Testing.Abstractions; 27 | 28 | namespace NUnit.Runner.Sinks 29 | { 30 | public class RemoteTestDiscoverySink : RemoteTestSink, ITestDiscoverySink 31 | { 32 | public RemoteTestDiscoverySink(BinaryWriter binaryWriter) : base(binaryWriter) 33 | { 34 | } 35 | 36 | public void SendTestFound(Test test) 37 | { 38 | if (test == null) 39 | throw new ArgumentNullException(nameof(test)); 40 | 41 | SendMessage(Messages.TestFound, test); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Sinks/RemoteTestExecutionSink.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.IO; 26 | using Microsoft.Extensions.Testing.Abstractions; 27 | 28 | namespace NUnit.Runner.Sinks 29 | { 30 | public class RemoteTestExecutionSink : RemoteTestSink, ITestExecutionSink 31 | { 32 | public RemoteTestExecutionSink(BinaryWriter binaryWriter) : base(binaryWriter) 33 | { 34 | } 35 | 36 | public void SendTestStarted(Test test) 37 | { 38 | if (test == null) 39 | throw new ArgumentNullException(nameof(test)); 40 | 41 | SendMessage(Messages.TestStarted, test); 42 | } 43 | 44 | public void SendTestResult(TestResult testResult) 45 | { 46 | if (testResult == null) 47 | throw new ArgumentNullException(nameof(testResult)); 48 | 49 | SendMessage(Messages.TestResult, testResult); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/Sinks/RemoteTestSink.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System.IO; 25 | using Microsoft.Extensions.Testing.Abstractions; 26 | using Newtonsoft.Json; 27 | using Newtonsoft.Json.Linq; 28 | 29 | namespace NUnit.Runner.Sinks 30 | { 31 | public class RemoteTestSink : ITestSink 32 | { 33 | protected BinaryWriter BinaryWriter { get; } 34 | 35 | protected RemoteTestSink(BinaryWriter binaryWriter) 36 | { 37 | BinaryWriter = binaryWriter; 38 | } 39 | 40 | public void SendTestCompleted() 41 | { 42 | SendMessage(Messages.TestCompleted); 43 | } 44 | 45 | public void SendWaitingCommand() 46 | { 47 | SendMessage(Messages.WaitingCommand); 48 | } 49 | 50 | protected void SendMessage(string messageType, object payload = null) 51 | { 52 | var msg = new Message 53 | { 54 | MessageType = messageType, 55 | Payload = payload != null ? JToken.FromObject(payload) : null 56 | }; 57 | var json = JsonConvert.SerializeObject(msg); 58 | BinaryWriter.Write(json); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/TestListeners/BaseTestListener.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.Xml.Linq; 26 | using Microsoft.Extensions.Testing.Abstractions; 27 | using NUnit.Runner.Extensions; 28 | using NUnit.Runner.Interfaces; 29 | using NUnit.Runner.Navigation; 30 | 31 | namespace NUnit.Runner.TestListeners 32 | { 33 | public abstract class BaseTestListener : ITestListener 34 | { 35 | readonly string _assemblyPath; 36 | readonly NavigationDataProvider _provider; 37 | 38 | protected CommandLineOptions Options { get; } 39 | 40 | /// 41 | /// Constructs a 42 | /// 43 | /// The command line options passed into this run 44 | /// The full path of the assembly that is being executed or explored 45 | public BaseTestListener(CommandLineOptions options, string assemblyPath) 46 | { 47 | Options = options; 48 | _assemblyPath = assemblyPath; 49 | _provider = NavigationDataProvider.GetNavigationDataProvider(assemblyPath); 50 | } 51 | 52 | public abstract void OnTestEvent(string xml); 53 | 54 | protected Test ParseTest(XElement xml) 55 | { 56 | var className = xml.Attribute("classname")?.Value; 57 | var methodName = xml.Attribute("methodname")?.Value; 58 | var sourceData = _provider?.GetSourceData(className, methodName); 59 | 60 | //use the _assemblyPath, the test case Id attribute, 61 | //and the fullName attribute to generate a unique signature 62 | //for this test. 63 | // 64 | //Originally, just the id was used, but the id from the 65 | //xml attribute is not sufficient, because different 66 | //projects in the same solution will generate the same 67 | //id. In "Design" mode, this causes a conflict within 68 | //Visual Studio and causes tests to get all whacked up. 69 | //This is a fix for dotnet-test-nunit#58 70 | // 71 | //However, another issue was discovered (dotnet-test-nunit#87) 72 | //Turns out, the assembly name and test id is also not sufficient. 73 | //During the discovery process, Visual Studio will not 74 | //update the internal value for FulluyQualifiedName for 75 | //a test if the Guid does not change. Therefore, if you 76 | //change the values of a TestCase, and they have the same 77 | //test ID, then visual Studio will ignore the new 78 | //FullyQualifiedName returned during test discovery. 79 | //While it ignores the new FullyQualifiedName, it will 80 | //update the DisplayName, which made debugging this 81 | //very frustrating. Nonetheless, to force a new 82 | //guid, we use the fullname of the testcase in the 83 | //Guid/signature generation. 84 | string uniqueName = xml.Attribute("id") 85 | + "|" 86 | + _assemblyPath 87 | + "|" 88 | + xml.Attribute("fullname")?.Value ?? ""; 89 | Guid testSignature = uniqueName.GetSignatureAsGuid(); 90 | 91 | var test = new Test 92 | { 93 | Id = testSignature, 94 | DisplayName = xml.Attribute("name")?.Value ?? "", 95 | FullyQualifiedName = xml.Attribute("fullname")?.Value ?? "", 96 | CodeFilePath = sourceData?.Filename, 97 | LineNumber = sourceData?.LineNumber 98 | }; 99 | // Add properties 100 | var properties = xml.Descendants("property"); 101 | foreach(var property in properties) 102 | { 103 | var name = property.Attribute("name")?.Value ?? ""; 104 | var value = property.Attribute("value")?.Value ?? ""; 105 | // TODO: When there is a way to support multiple categories, look 106 | // for the Category key and append them. 107 | test.Properties[name] = value; 108 | } 109 | return test; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/TestListeners/TestExecutionListener.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.Text.RegularExpressions; 26 | using System.Linq; 27 | using System.Xml.Linq; 28 | using Microsoft.Extensions.Testing.Abstractions; 29 | using NUnit.Runner.Extensions; 30 | 31 | namespace NUnit.Runner.TestListeners 32 | { 33 | public class TestEventArgs : EventArgs 34 | { 35 | public string TestName { get; } 36 | 37 | public string TestOutput { get; } 38 | 39 | public TestEventArgs(string testName, string testOutput) 40 | { 41 | TestName = testName; 42 | TestOutput = testOutput; 43 | } 44 | } 45 | public class TestOutputEventArgs : TestEventArgs 46 | { 47 | public string Stream { get; } 48 | 49 | public TestOutputEventArgs(string testName, string testOutput, string stream) 50 | : base(testName, testOutput) 51 | { 52 | Stream = stream; 53 | } 54 | } 55 | 56 | public class TestExecutionListener : BaseTestListener 57 | { 58 | public event EventHandler TestStarted; 59 | public event EventHandler TestFinished; 60 | public event EventHandler SuiteFinished; 61 | public event EventHandler TestOutput; 62 | 63 | readonly ITestExecutionSink _sink; 64 | 65 | public TestExecutionListener(ITestExecutionSink sink, CommandLineOptions options, string assemblyPath) 66 | : base(options, assemblyPath) 67 | { 68 | _sink = sink; 69 | } 70 | 71 | public override void OnTestEvent(string xml) 72 | { 73 | var element = XElement.Parse(xml); 74 | switch (element?.Name?.LocalName) 75 | { 76 | case "start-suite": 77 | break; 78 | case "test-suite": 79 | OnTestSuite(element); 80 | break; 81 | case "start-test": 82 | OnStartTest(element); 83 | break; 84 | case "test-case": 85 | OnTestCase(element); 86 | break; 87 | case "test-output": 88 | OnTestOutput(element); 89 | break; 90 | default: 91 | //Console.WriteLine(xml); 92 | break; 93 | } 94 | } 95 | 96 | void OnStartTest(XElement xml) 97 | { 98 | var test = ParseTest(xml); 99 | 100 | TestStarted?.Invoke(this, new TestEventArgs(test.FullyQualifiedName, null)); 101 | 102 | if (Options.DesignTime) 103 | _sink?.SendTestStarted(test); 104 | } 105 | 106 | void OnTestCase(XElement xml) 107 | { 108 | var testResult = ParseTestResult(xml); 109 | 110 | string output = null; 111 | 112 | if (testResult.Messages.Count > 0) 113 | output = testResult.Messages[0]; 114 | else if (testResult.Outcome != TestOutcome.None) 115 | output = testResult.Outcome.ToString(); 116 | 117 | TestFinished?.Invoke(this, new TestEventArgs(testResult.Test.FullyQualifiedName, output)); 118 | 119 | if (Options.DesignTime) 120 | _sink?.SendTestResult(testResult); 121 | } 122 | 123 | void OnTestSuite(XElement xml) 124 | { 125 | var testName = xml.Attribute("fullname")?.Value; 126 | var output = xml.Elements("output").FirstOrDefault()?.Value; 127 | 128 | SuiteFinished?.Invoke(this, new TestEventArgs(testName, output)); 129 | } 130 | 131 | void OnTestOutput(XElement xml) 132 | { 133 | var testName = xml.Attribute("testname")?.Value; 134 | var stream = xml.Attribute("stream")?.Value; 135 | var output = xml.Value; 136 | TestOutput?.Invoke(this, new TestOutputEventArgs(testName, output, stream)); 137 | } 138 | 139 | protected TestResult ParseTestResult(XElement xml) 140 | { 141 | var test = ParseTest(xml); 142 | var outcomeAttr = xml.Attribute("result").ConvertToTestOutcome(); 143 | 144 | var testResult = new TestResult(test) 145 | { 146 | StartTime = xml.Attribute("start-time").ConvertToDateTime(), 147 | EndTime = xml.Attribute("end-time").ConvertToDateTime(), 148 | Outcome = outcomeAttr, 149 | Duration = xml.Attribute("duration").ConvertToTimeSpan(outcomeAttr), 150 | ComputerName = Environment.MachineName 151 | }; 152 | // Output, Messages and stack traces 153 | testResult.ErrorMessage = GetErrorMessage(xml); 154 | testResult.ErrorStackTrace = xml.Element("failure")?.Element("stack-trace")?.Value; 155 | string messages = xml.Element("output")?.Value; 156 | if (!string.IsNullOrWhiteSpace(messages)) 157 | testResult.Messages.Add(messages); 158 | return testResult; 159 | } 160 | 161 | string GetErrorMessage(XElement xml) 162 | { 163 | var message = xml.Element("failure")?.Element("message")?.Value; 164 | if(!string.IsNullOrWhiteSpace(message)) 165 | { 166 | // If we're running in the IDE, remove any caret line from the message 167 | // since it will be displayed using a variable font and won't make sense. 168 | if (Options.DesignTime) 169 | { 170 | string pattern = Environment.NewLine + " -*\\^" + Environment.NewLine; 171 | message = Regex.Replace(message, pattern, Environment.NewLine, RegexOptions.Multiline); 172 | } 173 | } 174 | else 175 | { 176 | message = xml.Element("reason")?.Element("message")?.Value; 177 | } 178 | return message; 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/TestListeners/TestExploreListener.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.Xml.Linq; 26 | using Microsoft.Extensions.Testing.Abstractions; 27 | 28 | namespace NUnit.Runner.TestListeners 29 | { 30 | public class TestExploreListener : BaseTestListener 31 | { 32 | readonly ITestDiscoverySink _sink; 33 | 34 | public TestExploreListener(ITestDiscoverySink sink, CommandLineOptions options, string assemblyPath) 35 | : base(options, assemblyPath) 36 | { 37 | _sink = sink; 38 | } 39 | 40 | public override void OnTestEvent(string xml) 41 | { 42 | var element = XElement.Parse(xml); 43 | var tests = element.Descendants("test-case"); 44 | foreach(var test in tests) 45 | { 46 | OnTestCaseFound(test); 47 | } 48 | } 49 | 50 | void OnTestCaseFound(XElement testCase) 51 | { 52 | var test = ParseTest(testCase); 53 | if(Options.DesignTime) 54 | _sink.SendTestFound(test); 55 | else 56 | Console.WriteLine(test.FullyQualifiedName); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/dotnet-test-nunit.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | 7fc6dced-278a-449b-8bb0-95346410c8d2 10 | NUnit.Runner 11 | .\obj 12 | .\bin\ 13 | v4.6.1 14 | 15 | 16 | 2.0 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/dotnet-test-nunit/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "copyright": "Copyright (C) 2016 NUnit Project", 3 | "authors": [ "Rob Prouse" ], 4 | "title": "NUnit .NET Core Runner", 5 | "description": "NUnit console and Visual Studio runner for .NET Core and .NET 4.5.1+", 6 | "name": "dotnet-test-nunit", 7 | "version": "3.3.0", 8 | "buildOptions": { 9 | "emitEntryPoint": true, 10 | "preserveCompilationContext": true, 11 | "warningsAsErrors": true 12 | }, 13 | "packOptions": { 14 | "requireLicenseAcceptance": false, 15 | "tags": [ "testing", "tdd", "dotnet", "core", "nunit" ], 16 | "iconUrl": "https://cdn.rawgit.com/nunit/resources/master/images/icon/nunit_256.png", 17 | "licenseUrl": "https://raw.githubusercontent.com/nunit/dotnet-test-nunit/master/LICENSE", 18 | "projectUrl": "https://github.com/nunit/dotnet-test-nunit", 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/nunit/dotnet-test-nunit" 22 | } 23 | }, 24 | 25 | "dependencies": { 26 | "Microsoft.Extensions.Testing.Abstractions": "1.0.0-preview2-003121", 27 | "Microsoft.Extensions.DependencyModel": "1.0.0", 28 | "NUnit.Portable.Agent": "3.4.0-beta-3", 29 | "NUnit.Result.Writer.V2": "1.0.0" 30 | }, 31 | 32 | "frameworks": { 33 | "netcoreapp1.0": { 34 | "dependencies": { 35 | "Microsoft.NETCore.App": { 36 | "version": "1.0.0", 37 | "type": "platform" 38 | }, 39 | "System.Xml.XmlDocument": "4.0.1", 40 | "System.Xml.XPath.XmlDocument": "4.0.1" 41 | } 42 | }, 43 | "net451": { 44 | "dependencies": { 45 | "Microsoft.NETCore.Platforms": "1.0.1" 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test.runner/Program.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.Reflection; 26 | using NUnit.Common; 27 | using NUnit.Runner.Test.Sinks; 28 | using NUnitLite; 29 | 30 | namespace NUnit.Runner.Test.Runner 31 | { 32 | public class Program 33 | { 34 | // TODO: Once dotnet-test-nunit is capable of testing itself, remove this test runner 35 | public static int Main(string[] args) 36 | { 37 | var result = new AutoRun(typeof(RemoteTestDiscoverySinkTests).GetTypeInfo().Assembly) 38 | .Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); 39 | return result; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test.runner/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("NUnit Software")] 10 | [assembly: AssemblyProduct("dotnet_test_nunit.test.runner")] 11 | [assembly: AssemblyCopyright("Copyright (C) 2016 NUnit Project")] 12 | [assembly: AssemblyTrademark("NUnit is a trademark of NUnit Software")] 13 | 14 | // Setting ComVisible to false makes the types in this assembly not visible 15 | // to COM components. If you need to access a type in this assembly from 16 | // COM, set the ComVisible attribute to true on that type. 17 | [assembly: ComVisible(false)] 18 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test.runner/dotnet-test-nunit.test.runner.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | f2025265-8a4e-46dd-ae91-537e302b3f24 10 | NUnit.Runner.Test.Runner 11 | .\obj 12 | .\bin\ 13 | v4.6.1 14 | 15 | 16 | 2.0 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test.runner/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "copyright": "Copyright (C) 2016 NUnit Project", 3 | "authors": [ "Rob Prouse" ], 4 | "title": "NUnit .NET Core Runner Test Runner", 5 | "name": "dotnet-test-nunit.test.runner", 6 | "version": "3.4.0-*", 7 | "buildOptions": { 8 | "emitEntryPoint": true, 9 | "preserveCompilationContext": true, 10 | "warningsAsErrors": true 11 | }, 12 | 13 | "dependencies": { 14 | "NUnitLite": "3.5.0", 15 | "dotnet-test-nunit": { 16 | "target": "project" 17 | }, 18 | "dotnet-test-nunit.test": { 19 | "target": "project" 20 | } 21 | }, 22 | 23 | "frameworks": { 24 | "netcoreapp1.0": { 25 | "imports": "dotnet5.6", 26 | "dependencies": { 27 | "Microsoft.NETCore.App": { 28 | "type": "platform", 29 | "version": "1.0.0" 30 | }, 31 | "System.IO.FileSystem": "4.0.1", 32 | "System.Console": "4.0.0" 33 | } 34 | }, 35 | "net451": {} 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/ColorConsoleTests.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using NUnit.Framework; 26 | 27 | namespace NUnit.Runner.Test 28 | { 29 | [TestFixture] 30 | public class ColorConsoleTests 31 | { 32 | private ColorStyle _testStyle; 33 | 34 | [SetUp] 35 | public void SetUp() 36 | { 37 | // Find a test color that is different than the console color 38 | if (Console.ForegroundColor != ColorConsole.GetColor(ColorStyle.Error)) 39 | _testStyle = ColorStyle.Error; 40 | else if (Console.ForegroundColor != ColorConsole.GetColor(ColorStyle.Pass)) 41 | _testStyle = ColorStyle.Pass; 42 | else 43 | Assert.Inconclusive("Could not find a color to test with"); 44 | 45 | // Set to an unknown, unlikely color so that we can test for change 46 | Console.ForegroundColor = ConsoleColor.Magenta; 47 | 48 | Assume.That(Console.ForegroundColor, Is.EqualTo(ConsoleColor.Magenta), "Color tests cannot be run because the current console does not support color"); 49 | } 50 | 51 | [TearDown] 52 | public void TearDown() 53 | { 54 | Console.ResetColor(); 55 | } 56 | 57 | [Test] 58 | public void TestConstructor() 59 | { 60 | ConsoleColor expected = ColorConsole.GetColor(_testStyle); 61 | using (new ColorConsole(_testStyle)) 62 | { 63 | Assert.That(Console.ForegroundColor, Is.EqualTo(expected)); 64 | } 65 | Assert.That(Console.ForegroundColor, Is.Not.EqualTo(expected)); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/ColorStyleTests.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using NUnit.Framework; 26 | 27 | namespace NUnit.Runner.Test 28 | { 29 | [TestFixture] 30 | public class ColorStyleTests 31 | { 32 | // We can only test colors that are the same for all console backgrounds 33 | [TestCase(ColorStyle.Pass, ConsoleColor.Green)] 34 | [TestCase(ColorStyle.Failure, ConsoleColor.Red)] 35 | [TestCase(ColorStyle.Error, ConsoleColor.Red)] 36 | public void TestGetColor(ColorStyle style, ConsoleColor expected) 37 | { 38 | Assert.That(ColorConsole.GetColor(style), Is.EqualTo(expected)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/EnvTests.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using NUnit.Framework; 25 | 26 | namespace NUnit.Runner.Test 27 | { 28 | [TestFixture] 29 | public class EnvTests 30 | { 31 | [Test] 32 | public void DocumentFolderIsNotNull() 33 | { 34 | Assert.That(Env.DocumentFolder, Is.Not.Null.Or.Empty); 35 | } 36 | 37 | [Test] 38 | public void DefaultWorkDirectoryIsNotNull() 39 | { 40 | Assert.That(Env.DefaultWorkDirectory, Is.Not.Null.Or.Empty); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/Extensions/TestExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.Xml.Linq; 26 | using Microsoft.Extensions.Testing.Abstractions; 27 | using NUnit.Framework; 28 | using NUnit.Runner.Extensions; 29 | 30 | namespace NUnit.Runner.Test.Extensions 31 | { 32 | [TestFixture] 33 | public class TestExtensionsTests 34 | { 35 | [Test] 36 | public void CanConvertIdToGuid() 37 | { 38 | var attr = new XAttribute("id", "10"); 39 | var guid = attr.ConvertToGuid(); 40 | Assert.That(guid, Is.Not.EqualTo(Guid.Empty)); 41 | } 42 | 43 | [Test] 44 | public void NullIdConvertsToEmpty() 45 | { 46 | XAttribute attr = null; 47 | var guid = attr.ConvertToGuid(); 48 | Assert.That(guid, Is.EqualTo(Guid.Empty)); 49 | } 50 | 51 | [Test] 52 | public void CanConvertToDateTime() 53 | { 54 | var attr = new XAttribute("start-time", "2016-05-26 19:43:09Z"); 55 | var date = attr.ConvertToDateTime(); 56 | Assert.That(date.Year, Is.EqualTo(2016)); 57 | Assert.That(date.Month, Is.EqualTo(5)); 58 | Assert.That(date.Day, Is.EqualTo(26)); 59 | Assert.That(date.Hour, Is.EqualTo(19)); 60 | Assert.That(date.Minute, Is.EqualTo(43)); 61 | Assert.That(date.Second, Is.EqualTo(9)); 62 | Assert.That(date.Offset.TotalHours, Is.EqualTo(0d)); 63 | } 64 | 65 | [Test] 66 | public void NullDateTimeConvertsToNow() 67 | { 68 | XAttribute attr = null; 69 | var date = attr.ConvertToDateTime(); 70 | var now = DateTime.UtcNow; 71 | Assert.That(date.Year, Is.EqualTo(now.Year)); 72 | Assert.That(date.Month, Is.EqualTo(now.Month)); 73 | Assert.That(date.Day, Is.EqualTo(now.Day)); 74 | Assert.That(date.Hour, Is.EqualTo(now.Hour)); 75 | Assert.That(date.Minute, Is.EqualTo(now.Minute)); 76 | } 77 | 78 | [TestCase("1", 1d)] 79 | [TestCase("0.1", 0.1d)] 80 | [TestCase("0.001", 0.001d)] 81 | [TestCase("0.017533", 0.017533d)] 82 | [TestCase("0.0001", 0.001d, Description = "Minimum TimeSpan of 1 ms")] 83 | [TestCase("", 0.001d, Description = "Default TimeSpan of 1 ms")] 84 | public void CanConvertDurations(string duration, double expected) 85 | { 86 | var durationAttr = new XAttribute("duration", duration); 87 | var outcomeAttr = TestOutcome.Passed; 88 | 89 | var ts = durationAttr.ConvertToTimeSpan(outcomeAttr); 90 | Assert.That(ts.TotalSeconds, Is.EqualTo(expected).Within(0.001d)); 91 | } 92 | 93 | [TestCase("1", 0.0000001d)] 94 | [TestCase("", 0.0000001d)] 95 | public void IgnoredTestsHaveDurationOf1Tick(string duration, double expected) 96 | { 97 | var durationAttr = new XAttribute("duration", duration); 98 | var outcomeAttr = TestOutcome.Skipped; 99 | 100 | var ts = durationAttr.ConvertToTimeSpan(outcomeAttr); 101 | Assert.That(ts.TotalSeconds, Is.EqualTo(expected).Within(0.001d)); 102 | } 103 | 104 | [TestCase("Passed", TestOutcome.Passed)] 105 | [TestCase("Failed", TestOutcome.Failed)] 106 | [TestCase("Skipped", TestOutcome.Skipped)] 107 | [TestCase("Inconclusive", TestOutcome.Skipped)] 108 | [TestCase("", TestOutcome.None)] 109 | public void CanConvertTestOutcomes(string status, TestOutcome expected) 110 | { 111 | var attr = new XAttribute("status", status); 112 | var outcome = attr.ConvertToTestOutcome(); 113 | Assert.That(outcome, Is.EqualTo(expected)); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/Mocks/MockTestExecutionSink.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using Microsoft.Extensions.Testing.Abstractions; 25 | using MsTest = Microsoft.Extensions.Testing.Abstractions.Test; 26 | using MsTestResult = Microsoft.Extensions.Testing.Abstractions.TestResult; 27 | 28 | namespace NUnit.Runner.Test.Mocks 29 | { 30 | public class MockTestExecutionSink : ITestExecutionSink 31 | { 32 | public bool WaitingCommandReceived { get; private set; } 33 | 34 | public MsTest TestStarted { get; private set; } 35 | 36 | public bool TestCompletedReceived { get; private set; } 37 | 38 | public MsTestResult TestResult { get; private set; } 39 | 40 | public void SendWaitingCommand() 41 | { 42 | WaitingCommandReceived = true; 43 | } 44 | 45 | public void SendTestStarted(MsTest test) 46 | { 47 | TestStarted = test; 48 | } 49 | 50 | public void SendTestCompleted() 51 | { 52 | TestCompletedReceived = true; 53 | } 54 | 55 | public void SendTestResult(MsTestResult testResult) 56 | { 57 | TestResult = testResult; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/Mocks/MockTestExplorerSink.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using Microsoft.Extensions.Testing.Abstractions; 25 | using MsTest = Microsoft.Extensions.Testing.Abstractions.Test; 26 | 27 | namespace NUnit.Runner.Test.Mocks 28 | { 29 | public class MockTestExplorerSink : ITestDiscoverySink 30 | { 31 | public bool WaitingCommandReceived { get; private set; } 32 | 33 | public bool TestCompletedReceived { get; private set; } 34 | 35 | public MsTest TestFound { get; set; } 36 | 37 | public void SendWaitingCommand() 38 | { 39 | WaitingCommandReceived = true; 40 | } 41 | 42 | public void SendTestCompleted() 43 | { 44 | TestCompletedReceived = true; 45 | } 46 | 47 | public void SendTestFound(MsTest test) 48 | { 49 | TestFound = test; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/Navigation/NavigationDataProviderTests.cs: -------------------------------------------------------------------------------- 1 | // **************************************************************** 2 | // Copyright (c) 2016 NUnit Software. All rights reserved. 3 | // **************************************************************** 4 | 5 | using System.Reflection; 6 | using NUnit.Framework; 7 | using NUnit.Runner.Navigation; 8 | 9 | namespace NUnit.Runner.Test.Navigation 10 | { 11 | [TestFixture] 12 | public class NavigationDataProviderTests 13 | { 14 | const string Prefix = "NUnit.Runner.Test.Navigation.NavigationTestData"; 15 | 16 | NavigationDataProvider _provider; 17 | 18 | [SetUp] 19 | public void SetUp() 20 | { 21 | var path = typeof(NavigationDataProviderTests).GetTypeInfo().Assembly.Location; 22 | //string path = Path.Combine(Directory.GetCurrentDirectory(), "dotnet-test-nunit.test.dll"); 23 | _provider = NavigationDataProvider.GetNavigationDataProvider(path); 24 | Assert.That(_provider, Is.Not.Null, $"Could not create the NavigationDataProvider for {path}"); 25 | } 26 | 27 | [TestCase("", "EmptyMethod_OneLine", 9, 9)] 28 | [TestCase("", "EmptyMethod_TwoLines", 12, 13)] 29 | [TestCase("", "EmptyMethod_ThreeLines", 16, 17)] 30 | [TestCase("", "EmptyMethod_LotsOfLines", 20, 23)] 31 | [TestCase("", "SimpleMethod_Void_NoArgs", 26, 28)] 32 | [TestCase("", "SimpleMethod_Void_OneArg", 32, 33)] 33 | [TestCase("", "SimpleMethod_Void_TwoArgs", 38, 39)] 34 | [TestCase("", "SimpleMethod_ReturnsInt_NoArgs", 44, 46)] 35 | [TestCase("", "SimpleMethod_ReturnsString_OneArg", 50, 51)] 36 | // Generic method uses simple name 37 | [TestCase("", "GenericMethod_ReturnsString_OneArg", 55, 56)] 38 | [TestCase("", "AsyncMethod_Void", 60, 62)] 39 | [TestCase("", "AsyncMethod_Task", 67, 69)] 40 | [TestCase("", "AsyncMethod_ReturnsInt", 74, 76)] 41 | [TestCase("+NestedClass", "SimpleMethod_Void_NoArgs", 83, 85)] 42 | [TestCase("+ParameterizedFixture", "SimpleMethod_ReturnsString_OneArg", 101, 102)] 43 | // Generic Fixture requires ` plus type arg count 44 | [TestCase("+GenericFixture`2", "Matches", 116, 117)] 45 | [TestCase("+GenericFixture`2+DoublyNested", "WriteBoth", 132, 133)] 46 | [TestCase("+GenericFixture`2+DoublyNested`1", "WriteAllThree", 151, 152)] 47 | public void VerifyNavigationData(string suffix, string methodName, int debugLineNumber, int releaseLineNumber) 48 | { 49 | // Get the navigation data - ensure names are spelled correctly! 50 | var className = Prefix + suffix; 51 | var data = _provider.GetSourceData(className, methodName); 52 | Assert.NotNull(data, "Unable to retrieve navigation data"); 53 | 54 | // Verify the navigation data 55 | // Note that different line numbers are returned for our 56 | // debug and release builds, as follows: 57 | // 58 | // DEBUG 59 | // Min line: Opening curly brace. 60 | // Max line: Closing curly brace. 61 | // 62 | // RELEASE 63 | // Min line: First non-comment code line or closing 64 | // curly brace if the method is empty. 65 | // Max line: Last code line if that line is an 66 | // unconditional return statement, otherwise 67 | // the closing curly brace. 68 | Assert.That(data.Filename, Does.EndWith("NavigationTestData.cs")); 69 | #if DEBUG 70 | Assert.That(data.LineNumber, Is.EqualTo(debugLineNumber)); 71 | #else 72 | Assert.That(data.LineNumber, Is.EqualTo(releaseLineNumber)); 73 | #endif 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/Navigation/NavigationTestData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Threading.Tasks; 4 | namespace NUnit.Runner.Test.Navigation 5 | { 6 | // Contains methods used in testing use of DiaSession. 7 | class NavigationTestData 8 | { 9 | public void EmptyMethod_OneLine() { } // minLineDebug = minLineRelease = maxLineDebug = maxLineRelease = 8 10 | 11 | public void EmptyMethod_TwoLines() 12 | { // minLineDebug = 12 13 | } // minLineRelease = maxLineDebug = maxLineRelease = 13 14 | 15 | public void EmptyMethod_ThreeLines() 16 | { // minLineDebug = 16 17 | } // minLineRelease = maxLineDebug = maxLineRelease = 17 18 | 19 | public void EmptyMethod_LotsOfLines() 20 | { // minLineDebug = 20 21 | 22 | 23 | } // minLineRelease = maxLineDebug = maxLineRelease = 23 24 | 25 | public void SimpleMethod_Void_NoArgs() 26 | {// minLineDebug = 26 27 | const int answer = 42; 28 | Console.Write(answer); // minLineRelease = 28 29 | } // maxLineDebug = maxLineRelease = 29 30 | 31 | public void SimpleMethod_Void_OneArg(int x) 32 | { // minLineDebug = 32 33 | var answer = x; // minLineRelease = 33 34 | Console.Write(answer); 35 | } // maxLineDebug = maxLineRelease = 35 36 | 37 | public void SimpleMethod_Void_TwoArgs(int x, int y) 38 | { // minLineDebug = 38 39 | var answer = x + y; // minLineRelease = 39 40 | Console.Write(answer); 41 | } // maxLineDebug = maxLineRelease = 41 42 | 43 | public int SimpleMethod_ReturnsInt_NoArgs() 44 | {// minLineDebug = 44 45 | const int answer = 42; 46 | return answer; // minLineRelease = maxLineRelease = 46 47 | } // maxLineDebug = 47 48 | 49 | public string SimpleMethod_ReturnsString_OneArg(int x) 50 | { // minLineDebug = 50 51 | return x.ToString(CultureInfo.InvariantCulture); // minLineRelease = maxLineRelease = 51 52 | } // maxLineDebug = 52 53 | 54 | public string GenericMethod_ReturnsString_OneArg(T x) 55 | { // minLineDebug = 55 56 | return x.ToString(); // minLineRelease = maxLineRelease = 56 57 | } // maxLineDebug = 57 58 | 59 | public async void AsyncMethod_Void() 60 | { // minLineDebug = 60 61 | const int answer = 42; 62 | await Task.Delay(0); // minLineRelease = 62 63 | Console.Write(answer); 64 | } // maxLineDebug = maxLineRelease = 64 65 | 66 | public async Task AsyncMethod_Task() 67 | { // minLineDebug = 67 68 | const int answer = 42; 69 | await Task.Delay(0); // minLineRelease = 69 70 | Console.Write(answer); 71 | } // maxLineDebug = maxLineRelease = 71 72 | 73 | public async Task AsyncMethod_ReturnsInt() 74 | { // minLineDebug = 74 75 | const int answer = 42; 76 | await Task.Delay(0); // minLinerelease = 76 77 | return answer; 78 | } // maxLineDebug = maxLineRelease = 78 79 | 80 | public class NestedClass 81 | { 82 | public void SimpleMethod_Void_NoArgs() 83 | {// minLineDebug = 83 84 | const int answer = 42; 85 | Console.Write(answer); // minLineRelease = 85 86 | } // maxLineDebug = maxLineRelease = 86 87 | } 88 | 89 | public class ParameterizedFixture 90 | { 91 | private readonly double x; 92 | private readonly string s; 93 | 94 | public ParameterizedFixture(double x, string s) 95 | { 96 | this.x = x; 97 | this.s = s; 98 | } 99 | 100 | public string SimpleMethod_ReturnsString_OneArg(int i) 101 | { // minLineDebug = 101 102 | return s + x * i; // minLineRelease = maxLineRelease = 102 103 | } // maxLineDebug = 103 104 | } 105 | 106 | public class GenericFixture 107 | { 108 | private readonly T1 x; 109 | 110 | public GenericFixture(T1 x) 111 | { 112 | this.x = x; 113 | } 114 | 115 | public bool Matches(T2 y) 116 | { // minLineDebug = 116 117 | return x.Equals(y); // minLineRelease = maxLineRelease = 117 118 | } // maxLineDebug = 118 119 | 120 | public class DoublyNested 121 | { 122 | public T1 X; 123 | public T2 Y; 124 | 125 | public DoublyNested(T1 x, T2 y) 126 | { 127 | X = x; 128 | Y = y; 129 | } 130 | 131 | public void WriteBoth() 132 | { // minLineDebug = 132 133 | Console.Write(X + Y.ToString()); // minLineRelease = 133 134 | } // maxLineDebug = maxLineRelease = 134 135 | } 136 | 137 | public class DoublyNested 138 | { 139 | public T1 X; 140 | public T2 Y; 141 | public T3 Z; 142 | 143 | public DoublyNested(T1 x, T2 y, T3 z) 144 | { 145 | X = x; 146 | Y = y; 147 | Z = z; 148 | } 149 | 150 | public void WriteAllThree() 151 | { // minLineDebug = 151 152 | Console.Write(X + Y.ToString() + Z); // minLineRelease = 152 153 | } // maxLineDebug = maxLineRelease = 153 154 | } 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("NUnit Software")] 10 | [assembly: AssemblyProduct("dotnet_test_nunit.test")] 11 | [assembly: AssemblyCopyright("Copyright (C) 2016 NUnit Project")] 12 | [assembly: AssemblyTrademark("NUnit is a trademark of NUnit Software")] 13 | 14 | // Setting ComVisible to false makes the types in this assembly not visible 15 | // to COM components. If you need to access a type in this assembly from 16 | // COM, set the ComVisible attribute to true on that type. 17 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/Sinks/BaseSinkTests.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using System.IO; 26 | using Microsoft.Extensions.Testing.Abstractions; 27 | using Newtonsoft.Json; 28 | using NUnit.Framework; 29 | using MsTest = Microsoft.Extensions.Testing.Abstractions.Test; 30 | using MsTestResult = Microsoft.Extensions.Testing.Abstractions.TestResult; 31 | 32 | namespace NUnit.Runner.Test.Sinks 33 | { 34 | [TestFixture] 35 | public class BaseSinkTests 36 | { 37 | MemoryStream _stream; 38 | 39 | protected BinaryWriter BinaryWriter { get; private set; } 40 | 41 | [SetUp] 42 | public virtual void SetUp() 43 | { 44 | _stream = new MemoryStream(); 45 | BinaryWriter = new BinaryWriter(_stream); 46 | } 47 | 48 | [TearDown] 49 | public virtual void TearDown() 50 | { 51 | BinaryWriter.Dispose(); 52 | _stream.Dispose(); 53 | } 54 | 55 | protected Message GetMessage() 56 | { 57 | _stream.Position = 0; 58 | var reader = new BinaryReader(_stream); 59 | var json = reader.ReadString(); 60 | return JsonConvert.DeserializeObject(json); 61 | } 62 | 63 | protected T GetPayload(Message message) 64 | { 65 | Assert.That(message, Is.Not.Null); 66 | Assert.That(message.Payload, Is.Not.Null); 67 | return message.Payload.ToObject(); 68 | } 69 | 70 | protected static MsTest CreateMockTest() => 71 | new MsTest 72 | { 73 | Id = Guid.NewGuid(), 74 | DisplayName = "NUnitTest", 75 | FullyQualifiedName = "NUnit.Runner.Test.NUnitTest", 76 | CodeFilePath = @"C:\src\NUnitTest.cs", 77 | LineNumber = 123 78 | }; 79 | 80 | protected static MsTestResult CreateMockTestResult() 81 | { 82 | var test = CreateMockTest(); 83 | var endTime = DateTime.UtcNow; 84 | return new MsTestResult(test) 85 | { 86 | StartTime = endTime.AddSeconds(-2), 87 | EndTime = endTime, 88 | Duration = TimeSpan.FromSeconds(2), 89 | ComputerName = "MyComputer", 90 | ErrorMessage = "An error occured", 91 | ErrorStackTrace = "Stack trace", 92 | Outcome = TestOutcome.Failed 93 | }; 94 | } 95 | 96 | protected static void AssertAreEqual(MsTest expected, MsTest actual) 97 | { 98 | Assert.That(actual, Is.Not.Null); 99 | Assert.AreEqual(expected.Id, actual.Id); 100 | Assert.AreEqual(expected.DisplayName, actual.DisplayName); 101 | Assert.AreEqual(expected.FullyQualifiedName, actual.FullyQualifiedName); 102 | Assert.AreEqual(expected.CodeFilePath, actual.CodeFilePath); 103 | Assert.AreEqual(expected.LineNumber, actual.LineNumber); 104 | } 105 | 106 | protected static void AssertAreEqual(MsTestResult expected, MsTestResult actual) 107 | { 108 | Assert.That(actual, Is.Not.Null); 109 | Assert.AreEqual(expected.StartTime, actual.StartTime); 110 | Assert.AreEqual(expected.EndTime, actual.EndTime); 111 | Assert.AreEqual(expected.Duration, actual.Duration); 112 | Assert.AreEqual(expected.DisplayName, actual.DisplayName); 113 | Assert.AreEqual(expected.ComputerName, actual.ComputerName); 114 | Assert.AreEqual(expected.ErrorMessage, actual.ErrorMessage); 115 | Assert.AreEqual(expected.ErrorStackTrace, actual.ErrorStackTrace); 116 | Assert.AreEqual(expected.Outcome, actual.Outcome); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/Sinks/RemoteTestDiscoverySinkTests.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using Microsoft.Extensions.Testing.Abstractions; 25 | using NUnit.Framework; 26 | using NUnit.Runner.Sinks; 27 | using MsTest = Microsoft.Extensions.Testing.Abstractions.Test; 28 | 29 | namespace NUnit.Runner.Test.Sinks 30 | { 31 | [TestFixture] 32 | public class RemoteTestDiscoverySinkTests : BaseSinkTests 33 | { 34 | ITestDiscoverySink _testSink; 35 | 36 | [SetUp] 37 | public override void SetUp() 38 | { 39 | base.SetUp(); 40 | _testSink = new RemoteTestDiscoverySink(BinaryWriter); 41 | } 42 | 43 | [Test] 44 | public void SendTestFound() 45 | { 46 | var test = CreateMockTest(); 47 | _testSink.SendTestFound(test); 48 | var message = GetMessage(); 49 | Assert.That(message, Is.Not.Null); 50 | Assert.That(message.MessageType, Is.EqualTo(Messages.TestFound)); 51 | AssertAreEqual(test, GetPayload(message)); 52 | } 53 | 54 | [Test] 55 | public void SendTestFoundThrowsWithNullTest() 56 | { 57 | Assert.That(() => _testSink.SendTestFound(null), Throws.ArgumentNullException); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/Sinks/RemoteTestExecutionSinkTests.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using Microsoft.Extensions.Testing.Abstractions; 25 | using NUnit.Framework; 26 | using NUnit.Runner.Sinks; 27 | using MsTest = Microsoft.Extensions.Testing.Abstractions.Test; 28 | using MsTestResult = Microsoft.Extensions.Testing.Abstractions.TestResult; 29 | 30 | namespace NUnit.Runner.Test.Sinks 31 | { 32 | public class RemoteTestExecutionSinkTests : BaseSinkTests 33 | { 34 | ITestExecutionSink _testSink; 35 | 36 | [SetUp] 37 | public override void SetUp() 38 | { 39 | base.SetUp(); 40 | _testSink = new RemoteTestExecutionSink(BinaryWriter); 41 | } 42 | 43 | [Test] 44 | public void SendTestStarted() 45 | { 46 | var test = CreateMockTest(); 47 | _testSink.SendTestStarted(test); 48 | var message = GetMessage(); 49 | Assert.That(message, Is.Not.Null); 50 | Assert.That(message.MessageType, Is.EqualTo(Messages.TestStarted)); 51 | AssertAreEqual(test, GetPayload(message)); 52 | } 53 | 54 | [Test] 55 | public void SendTestStartedThrowsWithNullTest() 56 | { 57 | Assert.That(() => _testSink.SendTestStarted(null), Throws.ArgumentNullException); 58 | } 59 | 60 | [Test] 61 | public void SendTestResult() 62 | { 63 | var testResult = CreateMockTestResult(); 64 | _testSink.SendTestResult(testResult); 65 | var message = GetMessage(); 66 | Assert.That(message, Is.Not.Null); 67 | Assert.That(message.MessageType, Is.EqualTo(Messages.TestResult)); 68 | AssertAreEqual(testResult, GetPayload(message)); 69 | } 70 | 71 | [Test] 72 | public void SendTestResultThrowsWithNullTestResult() 73 | { 74 | Assert.That(() => _testSink.SendTestResult(null), Throws.ArgumentNullException); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/Sinks/RemoteTestSinkTests.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using Microsoft.Extensions.Testing.Abstractions; 25 | using NUnit.Framework; 26 | using NUnit.Runner.Sinks; 27 | 28 | namespace NUnit.Runner.Test.Sinks 29 | { 30 | [TestFixture] 31 | public class RemoteTestSinkTests : BaseSinkTests 32 | { 33 | ITestSink _testSink; 34 | 35 | [SetUp] 36 | public override void SetUp() 37 | { 38 | base.SetUp(); 39 | _testSink = new RemoteTestDiscoverySink(BinaryWriter); 40 | } 41 | 42 | [Test] 43 | public void SendTestCompleted() 44 | { 45 | _testSink.SendTestCompleted(); 46 | var message = GetMessage(); 47 | Assert.That(message, Is.Not.Null); 48 | Assert.That(message.MessageType, Is.EqualTo(Messages.TestCompleted)); 49 | } 50 | 51 | [Test] 52 | public void SendWaitingCommand() 53 | { 54 | _testSink.SendWaitingCommand(); 55 | var message = GetMessage(); 56 | Assert.That(message, Is.Not.Null); 57 | Assert.That(message.MessageType, Is.EqualTo(Messages.WaitingCommand)); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/TestListeners/TestExecutionListenerTests.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using Microsoft.Extensions.Testing.Abstractions; 26 | using NUnit.Framework; 27 | using NUnit.Runner.TestListeners; 28 | 29 | namespace NUnit.Runner.Test.TestListeners 30 | { 31 | [TestFixture] 32 | public class TestExecutionListenerTests 33 | { 34 | const string STARTED_TEST_CASE_XML = 35 | ""; 36 | 37 | const string SUCCESS_TEST_CASE_XML = 38 | ""; 39 | 40 | const string IGNORE_TEST_CASE_XML = 41 | "" + 42 | " " + 43 | " " + 44 | " " + 45 | " " + 46 | " " + 47 | " " + 48 | ""; 49 | 50 | const string EXPLICIT_TEST_CASE_XML = 51 | "" + 52 | " " + 53 | " " + 54 | " " + 55 | " " + 56 | " " + 57 | " " + 58 | ""; 59 | 60 | const string ERROR_TEST_CASE_XML = 61 | "" + 62 | " " + 63 | " " + 64 | " " + 65 | " " + 66 | ""; 67 | 68 | const string FAILED_TEST_CASE_XML = 69 | "" + 70 | " " + 71 | " " + 74 | " " + 76 | " " + 77 | ""; 78 | 79 | const string TESTCONTEXT_OUTPUT_TEST_CASE_XML = 80 | "" + 81 | " " + 83 | ""; 84 | 85 | 86 | const string TEST_SUITE_XML = 87 | "" + 88 | " " + 89 | " " + 90 | " " + 91 | " " + 92 | " " + 93 | " " + 94 | ""; 95 | 96 | const string TEST_OUTPUT = 97 | "This is the test output"; 98 | 99 | const string TEST_OUTPUT_WITH_CDATA = 100 | ""; 101 | 102 | Mocks.MockTestExecutionSink _sink; 103 | TestExecutionListener _listener; 104 | 105 | [OneTimeSetUp] 106 | public void OneTimeSetUp() 107 | { 108 | _sink = new Mocks.MockTestExecutionSink(); 109 | _listener = new TestExecutionListener(_sink, new CommandLineOptions("--designtime"), @"\src"); 110 | } 111 | 112 | [Test] 113 | public void CanParseSuccess() 114 | { 115 | var eventHandler = 116 | new EventHandler((sender, args) => Assert.That(args.TestOutput, Is.EqualTo("Passed"))); 117 | _listener.TestFinished += eventHandler; 118 | 119 | _listener.OnTestEvent(SUCCESS_TEST_CASE_XML); 120 | 121 | var testResult = _sink.TestResult; 122 | Assert.That(testResult, Is.Not.Null); 123 | Assert.That(testResult.ErrorMessage, Is.Null.Or.Empty); 124 | Assert.That(testResult.ErrorStackTrace, Is.Null.Or.Empty); 125 | Assert.That(testResult.Outcome, Is.EqualTo(TestOutcome.Passed)); 126 | Assert.That(testResult.StartTime.Hour, Is.EqualTo(23)); 127 | Assert.That(testResult.EndTime.Minute, Is.EqualTo(31)); 128 | Assert.That(testResult.Duration.TotalSeconds, Is.EqualTo(0.000001d).Within(0.001d)); 129 | 130 | _listener.TestFinished -= eventHandler; 131 | } 132 | 133 | [Test] 134 | public void CanParseIgnoredTests() 135 | { 136 | var eventHandler = 137 | new EventHandler((sender, args) => Assert.That(args.TestOutput, Is.EqualTo("Skipped"))); 138 | _listener.TestFinished += eventHandler; 139 | 140 | _listener.OnTestEvent(IGNORE_TEST_CASE_XML); 141 | var testResult = _sink.TestResult; 142 | Assert.That(testResult, Is.Not.Null); 143 | Assert.That(testResult.ErrorMessage, Is.EqualTo("Ignored Test")); 144 | Assert.That(testResult.ErrorStackTrace, Is.Null.Or.Empty); 145 | Assert.That(testResult.Outcome, Is.EqualTo(TestOutcome.Skipped)); 146 | Assert.That(testResult.StartTime.Hour, Is.EqualTo(23)); 147 | Assert.That(testResult.EndTime.Minute, Is.EqualTo(45)); 148 | Assert.That(testResult.Duration.TotalSeconds, Is.EqualTo(0.000001d).Within(0.001d)); 149 | 150 | _listener.TestFinished -= eventHandler; 151 | } 152 | 153 | [Test] 154 | public void CanParseExplicitTests() 155 | { 156 | var eventHandler = 157 | new EventHandler((sender, args) => Assert.That(args.TestOutput, Is.EqualTo("Skipped"))); 158 | _listener.TestFinished += eventHandler; 159 | 160 | _listener.OnTestEvent(EXPLICIT_TEST_CASE_XML); 161 | var testResult = _sink.TestResult; 162 | Assert.That(testResult, Is.Not.Null); 163 | Assert.That(testResult.ErrorMessage, Is.EqualTo("Explicit Test")); 164 | Assert.That(testResult.ErrorStackTrace, Is.Null.Or.Empty); 165 | Assert.That(testResult.Outcome, Is.EqualTo(TestOutcome.Skipped)); 166 | Assert.That(testResult.StartTime.Hour, Is.EqualTo(23)); 167 | Assert.That(testResult.EndTime.Minute, Is.EqualTo(45)); 168 | Assert.That(testResult.Duration.TotalSeconds, Is.EqualTo(0.000001d).Within(0.001d)); 169 | 170 | _listener.TestFinished -= eventHandler; 171 | } 172 | 173 | [Test] 174 | public void CanParseTestErrors() 175 | { 176 | var eventHandler = 177 | new EventHandler((sender, args) => Assert.That(args.TestOutput, Is.EqualTo("Failed"))); 178 | _listener.TestFinished += eventHandler; 179 | 180 | _listener.OnTestEvent(ERROR_TEST_CASE_XML); 181 | var testResult = _sink.TestResult; 182 | Assert.That(testResult, Is.Not.Null); 183 | Assert.That(testResult.ErrorMessage?.Trim(), Does.StartWith("System.ArgumentException")); 184 | Assert.That(testResult.ErrorStackTrace?.Trim(), Does.StartWith("at NUnitWithDotNetCoreRC2.Test.CalculatorTests.ErrorTest()")); 185 | Assert.That(testResult.Outcome, Is.EqualTo(TestOutcome.Failed)); 186 | Assert.That(testResult.StartTime.Hour, Is.EqualTo(19)); 187 | Assert.That(testResult.EndTime.Minute, Is.EqualTo(57)); 188 | Assert.That(testResult.Duration.TotalSeconds, Is.EqualTo(0.023031).Within(0.001d)); 189 | 190 | _listener.TestFinished -= eventHandler; 191 | } 192 | 193 | [Test] 194 | public void CanParseTestFailures() 195 | { 196 | var eventHandler = 197 | new EventHandler((sender, args) => Assert.That(args.TestOutput, Is.EqualTo("Failed"))); 198 | _listener.TestFinished += eventHandler; 199 | 200 | _listener.OnTestEvent(FAILED_TEST_CASE_XML); 201 | var testResult = _sink.TestResult; 202 | Assert.That(testResult, Is.Not.Null); 203 | Assert.That(testResult.ErrorMessage?.Trim(), Does.StartWith("Expected: 3")); 204 | Assert.That(testResult.ErrorStackTrace?.Trim(), Does.StartWith("at NUnitWithDotNetCoreRC2.Test.CalculatorTests.FailedTest()")); 205 | Assert.That(testResult.Outcome, Is.EqualTo(TestOutcome.Failed)); 206 | Assert.That(testResult.StartTime.Hour, Is.EqualTo(19)); 207 | Assert.That(testResult.EndTime.Minute, Is.EqualTo(57)); 208 | Assert.That(testResult.Duration.TotalSeconds, Is.EqualTo(0.017533).Within(0.001d)); 209 | 210 | _listener.TestFinished -= eventHandler; 211 | } 212 | 213 | [Test] 214 | public void CanParseTestOutput() 215 | { 216 | _listener.OnTestEvent(TESTCONTEXT_OUTPUT_TEST_CASE_XML); 217 | var testResult = _sink.TestResult; 218 | Assert.That(testResult, Is.Not.Null); 219 | Assert.That(testResult.Messages.Count, Is.EqualTo(1)); 220 | Assert.That(testResult.Messages[0], Does.StartWith("Test context output")); 221 | } 222 | 223 | [Test] 224 | public void FiresTestFinished() 225 | { 226 | string test = null; 227 | string output = null; 228 | _listener.TestFinished += (sender, args) => 229 | { 230 | test = args.TestName; 231 | output = args.TestOutput; 232 | }; 233 | 234 | _listener.OnTestEvent(TESTCONTEXT_OUTPUT_TEST_CASE_XML); 235 | 236 | Assert.That(test, Is.Not.Null); 237 | Assert.That(test, Is.EqualTo("NUnitWithDotNetCoreRC2.Test.CalculatorTests.TestWithTestContextOutput")); 238 | 239 | Assert.That(output, Is.Not.Null); 240 | Assert.That(output, Does.StartWith("Test context output")); 241 | } 242 | 243 | [Test] 244 | public void FiresSuiteFinished() 245 | { 246 | string test = null; 247 | _listener.SuiteFinished += (sender, args) => test = args.TestName; 248 | 249 | _listener.OnTestEvent(TEST_SUITE_XML); 250 | 251 | Assert.That(test, Is.Not.Null); 252 | Assert.That(test, Is.EqualTo("NUnit.Framework.Internal.CultureSettingAndDetectionTests.LoadWithFrenchCanadianCulture")); 253 | } 254 | 255 | [TestCase(TEST_OUTPUT, "NUnit.Output.Test", "This is the test output")] 256 | [TestCase(TEST_OUTPUT_WITH_CDATA, "NUnit.Output.CDataTest", "Test CData output")] 257 | public void FiresTestOutput(string xml, string expectedTest, string expectedOutput) 258 | { 259 | string test = null; 260 | string stream = null; 261 | string output = null; 262 | _listener.TestOutput += (sender, args) => 263 | { 264 | test = args.TestName; 265 | stream = args.Stream; 266 | output = args.TestOutput; 267 | }; 268 | 269 | _listener.OnTestEvent(xml); 270 | 271 | Assert.That(test, Is.Not.Null); 272 | Assert.That(test, Is.EqualTo(expectedTest)); 273 | 274 | Assert.That(output, Is.Not.Null); 275 | Assert.That(output, Is.EqualTo(expectedOutput)); 276 | 277 | Assert.That(stream, Is.Not.Null); 278 | Assert.That(stream, Is.EqualTo("theStream")); 279 | } 280 | 281 | [Test] 282 | public void TestStarted() 283 | { 284 | bool raised = false; 285 | 286 | var eventHandler = 287 | new EventHandler((sender, args) => raised = true); 288 | _listener.TestStarted += eventHandler; 289 | 290 | _listener.OnTestEvent(STARTED_TEST_CASE_XML); 291 | 292 | Assert.That(raised, Is.True); 293 | 294 | _listener.TestFinished -= eventHandler; 295 | } 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/TestListeners/TestExplorerListenerTests.cs: -------------------------------------------------------------------------------- 1 | // *********************************************************************** 2 | // Copyright (c) 2016 NUnit Project 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining 5 | // a copy of this software and associated documentation files (the 6 | // "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to 9 | // permit persons to whom the Software is furnished to do so, subject to 10 | // the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be 13 | // included in all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | // *********************************************************************** 23 | 24 | using System; 25 | using NUnit.Framework; 26 | using NUnit.Runner.TestListeners; 27 | 28 | namespace NUnit.Runner.Test.TestListeners 29 | { 30 | [TestFixture] 31 | public class TestExplorerListenerTests 32 | { 33 | const string TEST_CASE_XML_WITH_PROPERTIES = 34 | "" + 35 | " " + 36 | " " + 37 | " " + 38 | " " + 39 | " " + 40 | " " + 41 | ""; 42 | 43 | const string TEST_CASE_XML_WITH_MULTIPLE_CATEGORIES = 44 | "" + 45 | " " + 46 | " " + 47 | " " + 48 | " " + 49 | " " + 50 | " " + 51 | ""; 52 | 53 | Mocks.MockTestExplorerSink _sink; 54 | TestExploreListener _listener; 55 | 56 | [OneTimeSetUp] 57 | public void OneTimeSetUp() 58 | { 59 | _sink = new Mocks.MockTestExplorerSink(); 60 | _listener = new TestExploreListener(_sink, new CommandLineOptions("--designtime"), @"\src"); 61 | } 62 | 63 | [Test] 64 | public void CanParseTestsWithProperties() 65 | { 66 | _listener.OnTestEvent(TEST_CASE_XML_WITH_PROPERTIES); 67 | var test = _sink.TestFound; 68 | Assert.That(test, Is.Not.Null); 69 | Assert.That(test.DisplayName, Is.EqualTo("LoadWithFrenchCanadianCulture")); 70 | Assert.That(test.FullyQualifiedName, Is.EqualTo("NUnit.Framework.Internal.CultureSettingAndDetectionTests.LoadWithFrenchCanadianCulture")); 71 | Assert.That(test.Id, Is.Not.EqualTo(Guid.Empty)); 72 | Assert.That(test.Properties.Count, Is.EqualTo(2)); 73 | Assert.That(test.Properties["SetCulture"], Is.EqualTo("fr-CA")); 74 | Assert.That(test.Properties["UICulture"], Is.EqualTo("en-CA")); 75 | } 76 | 77 | [Test] 78 | public void CanParseTestsWithMultipleCategories() 79 | { 80 | _listener.OnTestEvent(TEST_CASE_XML_WITH_MULTIPLE_CATEGORIES); 81 | var test = _sink.TestFound; 82 | Assert.That(test, Is.Not.Null); 83 | Assert.That(test.DisplayName, Is.EqualTo("MultipleCategoryTest")); 84 | Assert.That(test.FullyQualifiedName, Is.EqualTo("NUnitWithDotNetCoreRC2.Test.CalculatorTests.MultipleCategoryTest")); 85 | Assert.That(test.Id, Is.Not.EqualTo(Guid.Empty)); 86 | // TODO: Visual Studio currently only supports a single category 87 | Assert.That(test.Properties.Count, Is.EqualTo(1)); 88 | Assert.That(test.Properties["Category"], Is.EqualTo("Two")); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/dotnet-test-nunit.test.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | b3c98a50-d42f-4197-968b-0e25591e83c3 10 | NUnit.Runner.Test 11 | .\obj 12 | .\bin\ 13 | v4.6.1 14 | 15 | 16 | 2.0 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/dotnet-test-nunit.test/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "copyright": "Copyright (C) 2016 NUnit Project", 3 | "authors": [ "Rob Prouse" ], 4 | "title": "NUnit .NET Core Runner Tests", 5 | "name": "dotnet-test-nunit.test", 6 | "version": "3.3.0-*", 7 | "buildOptions": { 8 | "preserveCompilationContext": true, 9 | "warningsAsErrors": true 10 | }, 11 | 12 | "dependencies": { 13 | "NUnit": "3.5.0", 14 | "dotnet-test-nunit": { 15 | "target": "project" 16 | } 17 | }, 18 | "testRunner": "nunit", 19 | 20 | "frameworks": { 21 | "netcoreapp1.0": { 22 | "imports": "dotnet5.6", 23 | "dependencies": { 24 | "Microsoft.NETCore.App": { 25 | "version": "1.0.0", 26 | "type": "platform" 27 | } 28 | } 29 | }, 30 | "net451": {} 31 | } 32 | } 33 | --------------------------------------------------------------------------------