Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blame for vstest #915

Merged
merged 10 commits into from
Jul 14, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion TestPlatform.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26326.0
VisualStudioVersion = 15.0.26605.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED0C35EB-7F31-4841-A24F-8EB708FFA959}"
EndProject
Expand Down Expand Up @@ -151,6 +151,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TestPlatform.Test
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TestPlatform.TestHostProvider", "src\Microsoft.TestPlatform.TestHostProvider\Microsoft.TestPlatform.TestHostProvider.csproj", "{11ECCB8B-6958-42A7-BD58-88C09CB149B2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TestPlatform.Extensions.BlameDataCollector", "src\Microsoft.TestPlatform.Extensions.BlameDataCollector\Microsoft.TestPlatform.Extensions.BlameDataCollector.csproj", "{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests", "test\Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests\Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests.csproj", "{488675EC-C8BB-40E0-AD4F-91F623D548B3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -785,6 +789,30 @@ Global
{11ECCB8B-6958-42A7-BD58-88C09CB149B2}.Release|x64.Build.0 = Release|Any CPU
{11ECCB8B-6958-42A7-BD58-88C09CB149B2}.Release|x86.ActiveCfg = Release|Any CPU
{11ECCB8B-6958-42A7-BD58-88C09CB149B2}.Release|x86.Build.0 = Release|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Debug|x64.ActiveCfg = Debug|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Debug|x64.Build.0 = Debug|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Debug|x86.ActiveCfg = Debug|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Debug|x86.Build.0 = Debug|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Release|Any CPU.Build.0 = Release|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Release|x64.ActiveCfg = Release|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Release|x64.Build.0 = Release|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Release|x86.ActiveCfg = Release|Any CPU
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A}.Release|x86.Build.0 = Release|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Debug|x64.ActiveCfg = Debug|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Debug|x64.Build.0 = Debug|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Debug|x86.ActiveCfg = Debug|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Debug|x86.Build.0 = Debug|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Release|Any CPU.Build.0 = Release|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Release|x64.ActiveCfg = Release|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Release|x64.Build.0 = Release|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Release|x86.ActiveCfg = Release|Any CPU
{488675EC-C8BB-40E0-AD4F-91F623D548B3}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -851,5 +879,7 @@ Global
{7B48115A-B766-4B55-93A8-C08A42C37710} = {B27FAFDF-2DBA-4AB0-BA85-FD5F21D359D6}
{FBF74C8F-695C-4967-84AC-358EEFB1376D} = {B27FAFDF-2DBA-4AB0-BA85-FD5F21D359D6}
{11ECCB8B-6958-42A7-BD58-88C09CB149B2} = {ED0C35EB-7F31-4841-A24F-8EB708FFA959}
{76D4BB7E-D981-42D5-BE96-6FAD8DEF9A4A} = {ED0C35EB-7F31-4841-A24F-8EB708FFA959}
{488675EC-C8BB-40E0-AD4F-91F623D548B3} = {B27FAFDF-2DBA-4AB0-BA85-FD5F21D359D6}
EndGlobalSection
EndGlobal
8 changes: 8 additions & 0 deletions scripts/build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@ function Publish-Package
Write-Verbose "Move-Item $coreCLR20PackageDir\$file $coreCLRExtensionsDir -Force"
Move-Item $coreCLR20PackageDir\$file $coreCLRExtensionsDir -Force
}

# Publish Datacollector
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Require change in build.sh

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this assembly be added for signing?

$TPB_TargetFrameworkStandard = "netstandard1.5"
$blameDataCollector = Join-Path $env:TP_ROOT_DIR "src\Microsoft.TestPlatform.Extensions.BlameDataCollector\bin\$TPB_Configuration"
$blameDataCollectorNet46 = Join-Path $blameDataCollector $TPB_TargetFramework
$blameDataCollectorNetStandard = Join-Path $blameDataCollector $TPB_TargetFrameworkStandard
Copy-Item $blameDataCollectorNet46\* $fullCLRExtensionsDir -Force
Copy-Item $blameDataCollectorNetStandard\* $coreCLRExtensionsDir -Force

# Note Note: If there are some dependencies for the TestHostRuntimeProvider assemblies, those need to be moved too.
$runtimeproviders = @("Microsoft.TestPlatform.TestHostRuntimeProvider.dll", "Microsoft.TestPlatform.TestHostRuntimeProvider.pdb")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ private void ProcessRequests(ITestRequestManager testRequestManager)

case MessageType.StartDiscovery:
{

var discoveryPayload = this.dataSerializer.DeserializePayload<DiscoveryRequestPayload>(message);
this.StartDiscovery(discoveryPayload, testRequestManager);
break;
Expand Down
1 change: 1 addition & 0 deletions src/Microsoft.TestPlatform.Common/Friends.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
[assembly: InternalsVisibleTo("Microsoft.TestPlatform.CommunicationUtilities.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
[assembly: InternalsVisibleTo("Microsoft.TestPlatform.Client.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
[assembly: InternalsVisibleTo("Microsoft.TestPlatform.Extensions.BlameDataCollector.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]

#endregion
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.Logging
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;

using CommonResources = Microsoft.VisualStudio.TestPlatform.Common.Resources.Resources;
using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework;

/// <summary>
/// Responsible for managing logger extensions and broadcasting results
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.TestPlatform.Extensions.BlameDataCollector
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;

using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection;

/// <summary>
/// The blame collector.
/// </summary>
[DataCollectorFriendlyName("Blame")]
[DataCollectorTypeUri("datacollector://Microsoft/TestPlatform/Extensions/Blame")]
public class BlameCollector : DataCollector, ITestExecutionEnvironmentSpecifier
{
private DataCollectionSink dataCollectionSink;
private DataCollectionEnvironmentContext context;
private DataCollectionEvents events;
private List<TestCase> testSequence;
private IBlameReaderWriter blameReaderWriter;
private int testStartCount;
private int testEndCount;

/// <summary>
/// Initializes a new instance of the <see cref="BlameCollector"/> class.
/// Using XmlReaderWriter by default
/// </summary>
public BlameCollector()
: this(new XmlReaderWriter())
{
}

/// <summary>
/// Initializes a new instance of the <see cref="BlameCollector"/> class.
/// </summary>
/// <param name="blameReaderWriter">
/// BlameReaderWriter instance.
/// </param>
protected BlameCollector(IBlameReaderWriter blameReaderWriter)
{
this.blameReaderWriter = blameReaderWriter;
}

/// <summary>
/// Gets environment variables that should be set in the test execution environment
/// </summary>
/// <returns>Environment variables that should be set in the test execution environment</returns>
public IEnumerable<KeyValuePair<string, string>> GetTestExecutionEnvironmentVariables()
{
return Enumerable.Empty<KeyValuePair<string, string>>();
}

/// <summary>
/// Initializes parameters for the new instance of the class <see cref="BlameDataCollector"/>
/// </summary>
/// <param name="configurationElement">The Xml Element to save to</param>
/// <param name="events">Data collection events to which methods subscribe</param>
/// <param name="dataSink">A data collection sink for data transfer</param>
/// <param name="logger">Data Collection Logger to send messages to the client </param>
/// <param name="environmentContext">Context of data collector environment</param>
public override void Initialize(
XmlElement configurationElement,
DataCollectionEvents events,
DataCollectionSink dataSink,
DataCollectionLogger logger,
DataCollectionEnvironmentContext environmentContext)
{
ValidateArg.NotNull(logger, nameof(logger));

this.events = events;
this.dataCollectionSink = dataSink;
this.context = environmentContext;
this.testSequence = new List<TestCase>();

// Subscribing to events
this.events.SessionEnd += this.SessionEnded_Handler;
this.events.TestCaseStart += this.EventsTestCaseStart;
this.events.TestCaseEnd += this.EventsTestCaseEnd;
}

/// <summary>
/// Called when Test Case Start event is invoked
/// </summary>
private void EventsTestCaseStart(object sender, TestCaseStartEventArgs e)
{
if(EqtTrace.IsInfoEnabled)
{
EqtTrace.Info("Blame Collector : Test Case Start");
}
this.testSequence.Add(e.TestElement);
this.testStartCount++;
}

/// <summary>
/// Called when Test Case End event is invoked
/// </summary>
private void EventsTestCaseEnd(object sender, TestCaseEndEventArgs e)
{
if (EqtTrace.IsInfoEnabled)
{
EqtTrace.Info("Blame Collector : Test Case End");
}
this.testEndCount++;
}

/// <summary>
/// Called when Session End event is invoked
/// </summary>
private void SessionEnded_Handler(object sender, SessionEndEventArgs args)
{
if (EqtTrace.IsInfoEnabled)
{
EqtTrace.Info("Blame Collector : Session End");
}

// If the last test crashes, it will not invoke a test case end and therefore
// In case of crash testStartCount will be greater than testEndCount and we need to send write the sequence
if (this.testStartCount > this.testEndCount)
{
var filepath = Path.Combine(AppContext.BaseDirectory, Constants.AttachmentFileName);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check filepath

filepath = this.blameReaderWriter.WriteTestSequence(this.testSequence, filepath);
var fileTranferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, filepath, true);
this.dataCollectionSink.SendFileAsync(fileTranferInformation);
}

this.DeregisterEvents();
}

/// <summary>
/// Method to deregister handlers and cleanup
/// </summary>
private void DeregisterEvents()
{
this.events.SessionEnd -= this.SessionEnded_Handler;
this.events.TestCaseStart -= this.EventsTestCaseStart;
this.events.TestCaseEnd -= this.EventsTestCaseEnd;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.TestPlatform.Extensions.BlameDataCollector
{
using System;
using System.Linq;

using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.Utilities;

/// <summary>
/// The blame logger.
/// </summary>
[FriendlyName(BlameLogger.FriendlyName)]
[ExtensionUri(BlameLogger.ExtensionUri)]
public class BlameLogger : ITestLogger
{
#region Constants

/// <summary>
/// Uri used to uniquely identify the Blame logger.
/// </summary>
public const string ExtensionUri = "logger://Microsoft/TestPlatform/Extensions/Blame";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version


/// <summary>
/// Alternate user friendly string to uniquely identify the Blame logger.
/// </summary>
public const string FriendlyName = "Blame";

/// <summary>
/// The blame reader writer.
/// </summary>
private readonly IBlameReaderWriter blameReaderWriter;

/// <summary>
/// The output.
/// </summary>
private readonly IOutput output;

#endregion

#region Constructor

/// <summary>
/// Initializes a new instance of the <see cref="BlameLogger"/> class.
/// </summary>
public BlameLogger()
: this(ConsoleOutput.Instance, new XmlReaderWriter())
{
}

/// <summary>
/// Constructor added for testing purpose
/// </summary>
/// <param name="output">Output Instance</param>
/// <param name="blameReaderWriter">BlameReaderWriter Instance</param>
protected BlameLogger(IOutput output, IBlameReaderWriter blameReaderWriter)
{
this.output = output;
this.blameReaderWriter = blameReaderWriter;
}

#endregion

#region ITestLogger

/// <summary>
/// Initializes the Logger.
/// </summary>
/// <param name="events">Events that can be registered for.</param>
/// <param name="testRunDictionary">Test Run Directory</param>
public void Initialize(TestLoggerEvents events, string testRunDictionary)
{
if (events == null)
{
throw new ArgumentNullException(nameof(events));
}
events.TestRunComplete += this.TestRunCompleteHandler;
}

/// <summary>
/// Called when a test run is complete.
/// </summary>
private void TestRunCompleteHandler(object sender, TestRunCompleteEventArgs e)
{
ValidateArg.NotNull<object>(sender, "sender");
ValidateArg.NotNull<TestRunCompleteEventArgs>(e, "e");

if (!e.IsAborted)
{
return;
}

this.output.WriteLine(string.Empty, OutputLevel.Information);

// Gets the faulty test case if test aborted
var testCaseName = this.GetFaultyTestCase(e);
if (testCaseName == string.Empty)
{
return;
}

var reason = Resources.Resources.AbortedTestRun + testCaseName;
this.output.Error(reason);
}

#endregion

#region Faulty test case fetch

/// <summary>
/// Fetches faulty test case
/// </summary>
/// <param name="e">
/// The TestRunCompleteEventArgs.
/// </param>
/// <returns>
/// Faulty test case name
/// </returns>
private string GetFaultyTestCase(TestRunCompleteEventArgs e)
{
foreach (var attachmentSet in e.AttachmentSets)
{
if (attachmentSet.DisplayName.Equals(Constants.BlameDataCollectorName))
{
var uriDataAttachment = attachmentSet.Attachments.LastOrDefault();
if (uriDataAttachment != null)
{
var filepath = uriDataAttachment.Uri.LocalPath;
var testCaseList = this.blameReaderWriter.ReadTestSequence(filepath);
if (testCaseList.Count > 0)
{
var testcase = testCaseList[testCaseList.Count - 1];
return testcase.FullyQualifiedName;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LastOrDefault

}
}

return string.Empty;
}
}

return string.Empty;
}

#endregion
}
}
Loading