From ef26f357e19838cb78b12a26a302436f03c6cf2f Mon Sep 17 00:00:00 2001 From: Rami Date: Sun, 15 Oct 2023 02:16:04 -0700 Subject: [PATCH] Added integration tests --- .github/workflows/build.yml | 1 - AzurePipelines.TestLogger.sln | 19 +- root | 0 .../AzurePipelines.TestLogger.csproj | 51 ++- .../AzurePipelinesTestLogger.cs | 28 +- src/AzurePipelines.TestLogger/LoggerQueue.cs | 48 +-- .../AzurePipelines.TestLogger.Tests.csproj | 7 +- .../CaptureRequestsMiddleware.cs | 26 ++ .../ClientMessage.cs | 5 + .../IRequestStore.cs | 9 + .../IntegrationTests.cs | 311 ++++++++++++++++++ ...ockAzureDevOpsTestRunLogCollectorServer.cs | 23 ++ .../RequestStore.cs | 9 + .../SampleUnitTestProject.csproj | 16 + tests/SampleUnitTestProject/UnitTest1.cs | 20 ++ 15 files changed, 515 insertions(+), 58 deletions(-) create mode 100644 root create mode 100644 tests/AzurePipelines.TestLogger.Tests/CaptureRequestsMiddleware.cs create mode 100644 tests/AzurePipelines.TestLogger.Tests/IRequestStore.cs create mode 100644 tests/AzurePipelines.TestLogger.Tests/IntegrationTests.cs create mode 100644 tests/AzurePipelines.TestLogger.Tests/MockAzureDevOpsTestRunLogCollectorServer.cs create mode 100644 tests/AzurePipelines.TestLogger.Tests/RequestStore.cs create mode 100644 tests/SampleUnitTestProject/SampleUnitTestProject.csproj create mode 100644 tests/SampleUnitTestProject/UnitTest1.cs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8b5f26b..401eed1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -72,7 +72,6 @@ jobs: run: | mkdir AzurePipelines.TestLogger.${{ env.SEM_VERSION }} copy ".\src\AzurePipelines.TestLogger\bin\${{ matrix.Configuration }}\netstandard1.5\*.*" .\AzurePipelines.TestLogger.${{ env.SEM_VERSION }} - copy "~\.nuget\packages\semver\2.0.6\lib\netstandard1.1\*.*" .\AzurePipelines.TestLogger.${{ env.SEM_VERSION }} copy ".\LICENSE" .\AzurePipelines.TestLogger.${{ env.SEM_VERSION }} copy ".\README.md" .\AzurePipelines.TestLogger.${{ env.SEM_VERSION }} copy ".\ReleaseNotes.md" .\AzurePipelines.TestLogger.${{ env.SEM_VERSION }} diff --git a/AzurePipelines.TestLogger.sln b/AzurePipelines.TestLogger.sln index a170b6e..27c4992 100644 --- a/AzurePipelines.TestLogger.sln +++ b/AzurePipelines.TestLogger.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31112.23 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34031.279 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C95ECC05-F3E8-49F4-B7C5-A29CD7EACFC1}" EndProject @@ -26,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{B8315F74-E stylecop.json = stylecop.json EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleUnitTestProject", "tests\SampleUnitTestProject\SampleUnitTestProject.csproj", "{AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -60,6 +62,18 @@ Global {8C42EBD4-FF36-44B6-A70E-7D83CB0626F8}.Release|x64.Build.0 = Release|Any CPU {8C42EBD4-FF36-44B6-A70E-7D83CB0626F8}.Release|x86.ActiveCfg = Release|Any CPU {8C42EBD4-FF36-44B6-A70E-7D83CB0626F8}.Release|x86.Build.0 = Release|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Debug|x64.ActiveCfg = Debug|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Debug|x64.Build.0 = Debug|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Debug|x86.ActiveCfg = Debug|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Debug|x86.Build.0 = Debug|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Release|Any CPU.Build.0 = Release|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Release|x64.ActiveCfg = Release|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Release|x64.Build.0 = Release|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Release|x86.ActiveCfg = Release|Any CPU + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -67,6 +81,7 @@ Global GlobalSection(NestedProjects) = preSolution {77CA5040-B4A0-4D0B-ADDD-09853A385007} = {C95ECC05-F3E8-49F4-B7C5-A29CD7EACFC1} {8C42EBD4-FF36-44B6-A70E-7D83CB0626F8} = {FA92AD98-1291-4A90-A3AA-ED81A9BBC86E} + {AFB35FB3-F22D-436A-84F7-A5DEFD879D3D} = {FA92AD98-1291-4A90-A3AA-ED81A9BBC86E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A7517899-6171-4E6B-BDD7-DBE01B34E83A} diff --git a/root b/root new file mode 100644 index 0000000..e69de29 diff --git a/src/AzurePipelines.TestLogger/AzurePipelines.TestLogger.csproj b/src/AzurePipelines.TestLogger/AzurePipelines.TestLogger.csproj index 33a95fa..2d6c726 100644 --- a/src/AzurePipelines.TestLogger/AzurePipelines.TestLogger.csproj +++ b/src/AzurePipelines.TestLogger/AzurePipelines.TestLogger.csproj @@ -1,27 +1,26 @@ - - - netstandard1.5 - 1.0.0 - 1.0.0.0 - 1.0.0.0 - + + + netstandard1.5 + 1.0.0 + 1.0.0.0 + 1.0.0.0 + + - - - - - - - - - - - - - <_Parameter1>AzurePipelines.TestLogger.Tests - - - <_Parameter1>DynamicProxyGenAssembly2 - - - + + + + + + + <_Parameter1>AzurePipelines.TestLogger.Tests + + + <_Parameter1>DynamicProxyGenAssembly2 + + + + + + + diff --git a/src/AzurePipelines.TestLogger/AzurePipelinesTestLogger.cs b/src/AzurePipelines.TestLogger/AzurePipelinesTestLogger.cs index b5db4a4..da5420a 100644 --- a/src/AzurePipelines.TestLogger/AzurePipelinesTestLogger.cs +++ b/src/AzurePipelines.TestLogger/AzurePipelinesTestLogger.cs @@ -28,6 +28,8 @@ public class AzurePipelinesTestLogger : ITestLoggerWithParameters public AzurePipelinesTestLogger() { + // For debugging purposes + // System.Diagnostics.Debugger.Launch(); _environmentVariableProvider = new EnvironmentVariableProvider(); _apiClientFactory = new ApiClientFactory(); } @@ -137,10 +139,28 @@ private void TestMessageHandler(object sender, TestRunMessageEventArgs e) // Add code to handle message } - private void TestResultHandler(object sender, TestResultEventArgs e) => - _queue.Enqueue(new VstpTestResult(e.Result)); + private void TestResultHandler(object sender, TestResultEventArgs e) + { + try + { + _queue.Enqueue(new VstpTestResult(e.Result)); + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + } + } - private void TestRunCompleteHandler(object sender, TestRunCompleteEventArgs e) => - _queue.Flush(new VstpTestRunComplete(e.IsAborted || e.IsCanceled, e.AttachmentSets)); + private void TestRunCompleteHandler(object sender, TestRunCompleteEventArgs e) + { + try + { + _queue.Flush(new VstpTestRunComplete(e.IsAborted || e.IsCanceled, e.AttachmentSets)); + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + } + } } } diff --git a/src/AzurePipelines.TestLogger/LoggerQueue.cs b/src/AzurePipelines.TestLogger/LoggerQueue.cs index 25df584..ca17eea 100644 --- a/src/AzurePipelines.TestLogger/LoggerQueue.cs +++ b/src/AzurePipelines.TestLogger/LoggerQueue.cs @@ -43,24 +43,17 @@ public void Flush(VstpTestRunComplete testRunComplete) // Cancel any idle consumers and let them return _queue.Cancel(); - try - { - // Any active consumer will circle back around and batch post the remaining queue - _consumeTask.Wait(TimeSpan.FromSeconds(60)); + // Any active consumer will circle back around and batch post the remaining queue + _consumeTask.Wait(TimeSpan.FromSeconds(60)); - // Update the run and parents to a completed state - SendTestsCompleted(testRunComplete, _consumeTaskCancellationSource.Token).Wait(TimeSpan.FromSeconds(60)); + // Update the run and parents to a completed state + SendTestsCompleted(testRunComplete, _consumeTaskCancellationSource.Token).Wait(TimeSpan.FromSeconds(60)); - // Cancel any active HTTP requests if still hasn't finished flushing - _consumeTaskCancellationSource.Cancel(); - if (!_consumeTask.Wait(TimeSpan.FromSeconds(10))) - { - throw new TimeoutException("Cancellation didn't happen quickly"); - } - } - catch (Exception ex) + // Cancel any active HTTP requests if still hasn't finished flushing + _consumeTaskCancellationSource.Cancel(); + if (!_consumeTask.Wait(TimeSpan.FromSeconds(10))) { - Console.WriteLine(ex); + throw new TimeoutException("Cancellation didn't happen quickly"); } } @@ -68,19 +61,26 @@ private async Task ConsumeItemsAsync(CancellationToken cancellationToken) { while (true) { - ITestResult[] nextItems = await _queue.TakeAsync().ConfigureAwait(false); - - if (nextItems == null || nextItems.Length == 0) + try { - // Queue is canceling and is empty - return; - } + ITestResult[] nextItems = await _queue.TakeAsync().ConfigureAwait(false); - await SendResultsAsync(nextItems, cancellationToken).ConfigureAwait(false); + if (nextItems == null || nextItems.Length == 0) + { + // Queue is canceling and is empty + return; + } - if (cancellationToken.IsCancellationRequested) + await SendResultsAsync(nextItems, cancellationToken).ConfigureAwait(false); + + if (cancellationToken.IsCancellationRequested) + { + return; + } + } + catch (Exception ex) { - return; + Console.WriteLine(ex); } } } diff --git a/tests/AzurePipelines.TestLogger.Tests/AzurePipelines.TestLogger.Tests.csproj b/tests/AzurePipelines.TestLogger.Tests/AzurePipelines.TestLogger.Tests.csproj index fcb8ca3..837ad1f 100644 --- a/tests/AzurePipelines.TestLogger.Tests/AzurePipelines.TestLogger.Tests.csproj +++ b/tests/AzurePipelines.TestLogger.Tests/AzurePipelines.TestLogger.Tests.csproj @@ -6,7 +6,11 @@ - + + + + + @@ -14,6 +18,7 @@ + diff --git a/tests/AzurePipelines.TestLogger.Tests/CaptureRequestsMiddleware.cs b/tests/AzurePipelines.TestLogger.Tests/CaptureRequestsMiddleware.cs new file mode 100644 index 0000000..55cd0e4 --- /dev/null +++ b/tests/AzurePipelines.TestLogger.Tests/CaptureRequestsMiddleware.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; + +namespace AzurePipelines.TestLogger.Tests +{ + public class CaptureRequestsMiddleware + { + private readonly RequestDelegate _next; + + public CaptureRequestsMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task Invoke(HttpContext context) + { + // Capture the incoming request and store it + IRequestStore requestStore = context.RequestServices.GetService(); + requestStore.Add(context.Request); + + // Call the next middleware in the pipeline + await _next(context); + } + } +} \ No newline at end of file diff --git a/tests/AzurePipelines.TestLogger.Tests/ClientMessage.cs b/tests/AzurePipelines.TestLogger.Tests/ClientMessage.cs index b8748f0..c51a544 100644 --- a/tests/AzurePipelines.TestLogger.Tests/ClientMessage.cs +++ b/tests/AzurePipelines.TestLogger.Tests/ClientMessage.cs @@ -47,5 +47,10 @@ public bool Equals(ClientMessage other) => private static string RemoveWhiteSpace(string str) => string.Concat(str.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries)); + + public override string ToString() + { + return $"Method: {Method}, Endpoint: {Endpoint}, ApiVersion: {ApiVersion}, Body: {Body}"; + } } } diff --git a/tests/AzurePipelines.TestLogger.Tests/IRequestStore.cs b/tests/AzurePipelines.TestLogger.Tests/IRequestStore.cs new file mode 100644 index 0000000..2971d86 --- /dev/null +++ b/tests/AzurePipelines.TestLogger.Tests/IRequestStore.cs @@ -0,0 +1,9 @@ +using Microsoft.AspNetCore.Http; + +namespace AzurePipelines.TestLogger.Tests +{ + internal interface IRequestStore + { + void Add(HttpRequest item); + } +} \ No newline at end of file diff --git a/tests/AzurePipelines.TestLogger.Tests/IntegrationTests.cs b/tests/AzurePipelines.TestLogger.Tests/IntegrationTests.cs new file mode 100644 index 0000000..a68fc55 --- /dev/null +++ b/tests/AzurePipelines.TestLogger.Tests/IntegrationTests.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using SampleUnitTestProject; + +namespace AzurePipelines.TestLogger.Tests +{ + [TestFixture] + public class IntegrationTests + { + private string _vsTestExeFilePath; + private string _sampleUnitTestProjectDllFilePath; + private string _vsTestLoggerDllPath; + private StringBuilder _outputAndError; + + [OneTimeSetUp] + public void SetUpFixture() + { + _vsTestExeFilePath = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), + "Microsoft Visual Studio", + "2022", + "Enterprise", + "Common7", + "IDE", + "CommonExtensions", + "Microsoft", + "TestWindow", + "vstest.console.exe"); + + string configuration = "Debug"; + +#if RELEASE + configuration = "Release"; +#endif + + string rootRepositoryPath = GetRootRepositoryPath(); + _sampleUnitTestProjectDllFilePath = Path.Combine(rootRepositoryPath, $@"tests\SampleUnitTestProject\bin\{configuration}\netcoreapp2.1\SampleUnitTestProject.dll"); + _vsTestLoggerDllPath = Path.Combine(rootRepositoryPath, $@"src\AzurePipelines.TestLogger\bin\{configuration}\netstandard1.5"); + } + + [SetUp] + public void SetUp() + { + _outputAndError?.Clear(); + _outputAndError = new StringBuilder(); + } + + [Test] + public void ExecuteTest_WithInvalidAzureDevopsCollectionUri_ContinuesTestExecution() + { + // Given + string fullyQualifiedTestMethodName = GetFullyQualifiedTestMethodName( + typeof(UnitTest1), + nameof(UnitTest1.TestMethod)); + + const string collectionUri = "collectionUri"; + + // When + int exitCode = ExecuteUnitTestWithLogger( + testMethod: fullyQualifiedTestMethodName, + collectionUri: collectionUri); + + // Then + Assert.AreEqual(0, exitCode); + } + + [Test] + public async Task ExecuteTest_WithDataTestMethod_LogsEachDataRow() + { + // Given + string fullyQualifiedTestMethodName = GetFullyQualifiedTestMethodName( + typeof(UnitTest1), + nameof(UnitTest1.DataTestMethod)); + + // When + TestResults testResults = await StartServerAndExecuteUnitTestWithLoggerAsync( + fullyQualifiedTestMethodName); + + // Then + Assert.AreEqual(0, testResults.ExitCode); + Assert.AreEqual(2, testResults.CapturedRequests.Count); + } + + private async Task StartServerAndExecuteUnitTestWithLoggerAsync( + string fullyQualifiedTestMethodName) + { + // Create the Server + IRequestStore requestStore = new RequestStore(); + + IWebHost host = WebHost.CreateDefaultBuilder() + .UseKestrel() + .ConfigureServices(configureServices => + { + configureServices.AddSingleton(requestStore); + }) + .UseUrls("http://127.0.0.1:0") // listen on a random available port + .UseStartup() + .Build(); + + await host.StartAsync(); + + try + { + // Get the server's listening address + IServerAddressesFeature serverAddresses = host.Services + .GetRequiredService() + .Features.Get(); + + string serverUrl = serverAddresses.Addresses.First(); + + Console.WriteLine($"Server is listening on: {serverUrl}"); + + int exitCode = ExecuteUnitTestWithLogger( + testMethod: fullyQualifiedTestMethodName, + collectionUri: $"{serverUrl}/"); + + List capturedRequests = (List)requestStore; + + return new TestResults + { + ExitCode = exitCode, + CapturedRequests = capturedRequests, + }; + } + finally + { + await host.StopAsync(); + } + } + + private class TestResults + { + public int ExitCode { get; set; } + public List CapturedRequests { get; set; } + } + + private static string GetFullyQualifiedTestMethodName(Type type, string methodName) + { + MethodInfo methodInfo = type.GetMethod(methodName); + return $"{type.Namespace}.{type.Name}.{methodInfo.Name}"; + } + + private int ExecuteUnitTestWithLogger( + bool verbose = true, + bool useDefaultCredentials = true, + string apiVersion = "3.0-preview.2", + bool groupTestResultsByClassName = false, + string testMethod = "SampleUnitTestProject.UnitTest1.TestMethod1", + string collectionUri = "collectionUri", + string teamProject = "teamProject", + string buildId = "buildId", + string buildRequestedFor = "buildRequestedFor", + string agentName = "agentName", + string agentJobName = "jobName") + { + List loggerArguments = new List + { + "AzurePipelines", + $"Verbose={verbose}", + $"UseDefaultCredentials={useDefaultCredentials}", + $"ApiVersion={apiVersion}", + $"GroupTestResultsByClassName={groupTestResultsByClassName}" + }; + + List arguments = new List + { + $"\"{_sampleUnitTestProjectDllFilePath}\"", + $"/Tests:{testMethod}", + $"/logger:\"{string.Join(";", loggerArguments)}\"", + $"/TestAdapterPath:\"{_vsTestLoggerDllPath}\"" + }; + + Console.WriteLine($"\"{_vsTestExeFilePath}\" {string.Join(" ", arguments)}"); + + ProcessStartInfo startInfo = new ProcessStartInfo + { + FileName = _vsTestExeFilePath, + Arguments = string.Join(" ", arguments), + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true, + }; + + // Set environment variables + foreach (KeyValuePair environmentVariable in new Dictionary + { + { EnvironmentVariableNames.TeamFoundationCollectionUri, collectionUri }, + { EnvironmentVariableNames.TeamProject, teamProject }, + { EnvironmentVariableNames.BuildId, buildId }, + { EnvironmentVariableNames.BuildRequestedFor, buildRequestedFor }, + { EnvironmentVariableNames.AgentName, agentName }, + { EnvironmentVariableNames.AgentJobName, agentJobName }, + }) + { + if (collectionUri != null) + { + startInfo.EnvironmentVariables[environmentVariable.Key] = environmentVariable.Value; + } + } + + StringBuilder output = new StringBuilder(); + StringBuilder error = new StringBuilder(); + StringBuilder outputAndError = new StringBuilder(); + + // Start the process + using (Process process = new Process { StartInfo = startInfo }) + { + process.Start(); + + Thread stdOutReaderThread = null; + Thread stdErrReaderThread = null; + + // Invoke stdOut and stdErr readers - each + // has its own thread to guarantee that they aren't + // blocked by, or cause a block to, the actual + // process running (or the gui). + stdOutReaderThread = new Thread(this.ReadStdOut); + stdOutReaderThread.Start(process); + stdErrReaderThread = new Thread(this.ReadStdErr); + stdErrReaderThread.Start(process); + + process.WaitForExit(); + int exitCode = process.ExitCode; + + if (stdOutReaderThread != null) + { + // wait for thread + stdOutReaderThread.Join(); + } + + if (stdErrReaderThread != null) + { + // wait for thread + stdErrReaderThread.Join(); + } + + Console.WriteLine($"Output:\n{_outputAndError.ToString()}"); + + // Check the exit code + Console.WriteLine($"Exit Code: {exitCode}"); + + return exitCode; + } + } + + private void ReadStdOut(object processObj) + { + try + { + string str; + while ((str = ((Process)processObj).StandardOutput.ReadLine()) != null) + { + _outputAndError.AppendLine(str); + } + } + catch + { + } + } + + private void ReadStdErr(object processObj) + { + try + { + string str; + while ((str = ((Process)processObj).StandardError.ReadLine()) != null) + { + _outputAndError.AppendLine(str); + } + } + catch + { + } + } + + private static string GetRootRepositoryPath() + { + string currentDirectory = Directory.GetCurrentDirectory(); + string fileNameToFind = "root"; + + // Start from the current directory and move up the directory tree + while (!File.Exists(Path.Combine(currentDirectory, fileNameToFind))) + { + string parentDirectory = Directory.GetParent(currentDirectory)?.FullName; + if (parentDirectory == null || parentDirectory == currentDirectory) + { + throw new Exception($"Failed to find file '{fileNameToFind}' in the directory tree."); + } + + currentDirectory = parentDirectory; + } + + return currentDirectory; + } + } +} diff --git a/tests/AzurePipelines.TestLogger.Tests/MockAzureDevOpsTestRunLogCollectorServer.cs b/tests/AzurePipelines.TestLogger.Tests/MockAzureDevOpsTestRunLogCollectorServer.cs new file mode 100644 index 0000000..91a7edf --- /dev/null +++ b/tests/AzurePipelines.TestLogger.Tests/MockAzureDevOpsTestRunLogCollectorServer.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; + +namespace AzurePipelines.TestLogger.Tests +{ + internal class MockAzureDevOpsTestRunLogCollectorServer + { + public void ConfigureServices(IServiceCollection services) + { + services.AddMvcCore(); + } + + public void Configure(IApplicationBuilder app) + { + app.UseMvc(routes => + { + routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}"); + }); + + app.UseMiddleware(); + } + } +} \ No newline at end of file diff --git a/tests/AzurePipelines.TestLogger.Tests/RequestStore.cs b/tests/AzurePipelines.TestLogger.Tests/RequestStore.cs new file mode 100644 index 0000000..5e23bd9 --- /dev/null +++ b/tests/AzurePipelines.TestLogger.Tests/RequestStore.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Http; + +namespace AzurePipelines.TestLogger.Tests +{ + internal class RequestStore : List, IRequestStore + { + } +} diff --git a/tests/SampleUnitTestProject/SampleUnitTestProject.csproj b/tests/SampleUnitTestProject/SampleUnitTestProject.csproj new file mode 100644 index 0000000..e1717b2 --- /dev/null +++ b/tests/SampleUnitTestProject/SampleUnitTestProject.csproj @@ -0,0 +1,16 @@ + + + netcoreapp2.1 + Library + false + + + + + 2.2.10 + + + 2.2.10 + + + \ No newline at end of file diff --git a/tests/SampleUnitTestProject/UnitTest1.cs b/tests/SampleUnitTestProject/UnitTest1.cs new file mode 100644 index 0000000..8bc54dc --- /dev/null +++ b/tests/SampleUnitTestProject/UnitTest1.cs @@ -0,0 +1,20 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace SampleUnitTestProject +{ + [TestClass] + public class UnitTest1 + { + [TestMethod] + public void TestMethod() + { + } + + [DataTestMethod] + [DataRow(1)] + [DataRow(2)] + public void DataTestMethod(int parameter) + { + } + } +}