Skip to content

Commit

Permalink
#25 Support test metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolayPianikov authored and NikolayPianikov committed Dec 11, 2018
1 parent 69c68d9 commit 893d2d0
Show file tree
Hide file tree
Showing 13 changed files with 151 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,53 @@ public void TestStdOut()
{
DoTest(x => x.WriteStdOutput("outp4uz"), "##teamcity[testStdOut name='BadaBumBigBadaBum' out='outp4uz' tc:tags='tc:parseServiceMessagesInside']");
}

[Test]
public void TestWriteTextValue()
{
DoTest(x => x.WriteValue("strVal", "myVal"), "##teamcity[testMetadata testName='BadaBumBigBadaBum' value='strVal' name='myVal']");
}

[Test]
[TestCase(1.0d, "1")]
[TestCase(0.0d, "0")]
[TestCase(-1.0d, "-1")]
[TestCase(1.33d, "1.33")]
[TestCase(-1.33d, "-1.33")]
[TestCase(0.33d, "0.33")]
public void TestWriteNumber(double value, string expectedValueInMessage)
{
DoTest(x => x.WriteValue(value, "myVal"), "##teamcity[testMetadata testName='BadaBumBigBadaBum' type='number' value='" + expectedValueInMessage + "' name='myVal']");
}

[Test]
public void TestWriteLink()
{
DoTest(x => x.WriteLink("http://abc.com", "abc"), "##teamcity[testMetadata testName='BadaBumBigBadaBum' type='link' value='http://abc.com' name='abc']");
}

[Test]
public void TestWriteFile()
{
DoTest(x => x.WriteFile("abc.txt", "abc"), "##teamcity[testMetadata testName='BadaBumBigBadaBum' type='artifact' value='abc.txt' name='abc']");
}

[Test]
public void TestWriteFileWithoutDescription()
{
DoTest(x => x.WriteFile("abc.txt"), "##teamcity[testMetadata testName='BadaBumBigBadaBum' type='artifact' value='abc.txt']");
}

[Test]
public void TestWriteImage()
{
DoTest(x => x.WriteImage("abc.jpg", "abc"), "##teamcity[testMetadata testName='BadaBumBigBadaBum' type='image' value='abc.jpg' name='abc']");
}

[Test]
public void TestWriteImageWithoutDescription()
{
DoTest(x => x.WriteImage("abc.jpg"), "##teamcity[testMetadata testName='BadaBumBigBadaBum' type='image' value='abc.jpg']");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ private void DoTestImpl(Action<T> action, Func<string, string> replace, string[]
var actualText = "\r\n" + string.Join("\r\n", actual);
var expected = preprocess(string.Join("\r\n", golds));

if (actual.Count() != expected.Count())
if (actual.Length != expected.Length)
Assert.Fail("Incorrect number of messages. Was: " + actualText);

for (var i = 0; i < actual.Count(); i++)
Assert.AreEqual(actual[i], expected[i], "Message {0} does not match. Was: {1}", i, actualText);
Assert.AreEqual(expected[i], actual[i], "Message {0} does not match. Was: {1}", i, actualText);
}

protected class ToStringProcessor : IServiceMessageProcessor
Expand Down
2 changes: 2 additions & 0 deletions TeamCity.ServiceMessages.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@
&lt;/Patterns&gt;</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/AddImportsToDeepestScope/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special
{
/// <summary>
/// Service messages for dynamically publish artifacts.
/// http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-PublishingArtifactswhiletheBuildisStillinProgress
/// http://confluence.jetbrains.net/display/TCD18/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-PublishingArtifactswhiletheBuildisStillinProgress
/// </summary>
/// <remarks>
/// Implementation is not thread-safe. Create an instance for each thread instead.
Expand All @@ -27,7 +27,7 @@ public interface ITeamCityArtifactsWriter
{
/// <summary>
/// attaches new artifact publishing rules as described in
/// http://confluence.jetbrains.net/display/TCD7/Build+Artifact
/// http://confluence.jetbrains.net/display/TCD18/Build+Artifact
/// </summary>
/// <param name="rules"></param>
void PublishArtifact([NotNull] string rules);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special
/// <pre>##teamcity[blockOpened name='&lt;blockName>']</pre>
/// and
/// <pre>##teamcity[blockClosed name='&lt;blockName>']</pre>
/// http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-BlocksofServiceMessages
/// http://confluence.jetbrains.net/display/TCD18/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-BlocksofServiceMessages
/// </summary>
/// <remarks>
/// Implementation is not thread-safe. Create an instance for each thread instead.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special
{
/// <summary>
/// Interface for writing build-related messages
/// http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingBuildNumber
/// http://confluence.jetbrains.net/display/TCD18/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingBuildNumber
/// </summary>
/// <remarks>
/// Implementation is not thread-safe. Create an instance for each thread instead.
Expand All @@ -41,7 +41,7 @@ public interface ITeamCityBuildStatusWriter

/// <summary>
/// Generates service message to update build parameter
/// http://confluence.jetbrains.net/display/TCD7/Configuring+Build+Parameters
/// http://confluence.jetbrains.net/display/TCD18/Configuring+Build+Parameters
/// </summary>
/// <param name="parameterName">
/// parameter name, could start with env. for environment, system. for system property,
Expand All @@ -53,7 +53,7 @@ public interface ITeamCityBuildStatusWriter

/// <summary>
/// Generates service message to report build statistics values
/// http://confluence.jetbrains.net/display/TCD7/Customizing+Statistics+Charts#CustomizingStatisticsCharts-customCharts
/// http://confluence.jetbrains.net/display/TCD18/Customizing+Statistics+Charts#CustomizingStatisticsCharts-customCharts
/// </summary>
/// <param name="statisticsKey">statistics report key</param>
/// <param name="statisticsValue">statistics report values</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special
/// <pre>##teamcity[compilationStarted compiler='&lt;compiler name>']</pre>
/// and
/// <pre>##teamcity[compilationFinished compiler='&lt;compiler name>']</pre>
/// http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingCompilationMessages
/// http://confluence.jetbrains.net/display/TCD18/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingCompilationMessages
/// </summary>
/// <remarks>
/// Implementation is not thread-safe. Create an instance for each thread instead.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special
/// <pre>
/// ##teamcity[message text='&lt;message text>' errorDetails='&lt;error details>' status='&lt;status value>']
/// </pre>
/// http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingMessagesForBuildLog
/// http://confluence.jetbrains.net/display/TCD18/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingMessagesForBuildLog
/// </summary>
/// <remarks>
/// Implementation is not thread-safe. Create an instance for each thread instead.
Expand Down
37 changes: 36 additions & 1 deletion TeamCity.ServiceMessages/Write/Special/ITeamCityTestWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,44 @@ public interface ITeamCityTestWriter : IDisposable
/// Specifies test duration
/// </summary>
/// <remarks>
/// TeamCity may compute test duration inself, to provide precise data, you may set the duration explicitly
/// TeamCity may compute test duration itself, to provide precise data, you may set the duration explicitly
/// </remarks>
/// <param name="duration">time of test</param>
void WriteDuration(TimeSpan duration);

/// <summary>
/// Writes image as test metadata. Supported in TeamCity 2018.2+ https://confluence.jetbrains.com/display/TCD18/Reporting+Test+Metadata.
/// </summary>
/// <param name="teamCityArtifactUri">The URI to the image in the build artifacts directory. Should be relative to the build artifacts directory.</param>
/// <param name="description">The image description. When showing images, TeamCity shows both the ‘description’ and the filename of the referenced image.</param>
void WriteImage([NotNull] string teamCityArtifactUri, [NotNull] string description = "");

/// <summary>
/// Writes file as test metadata. Supported in TeamCity 2018.2+ https://confluence.jetbrains.com/display/TCD18/Reporting+Test+Metadata.
/// </summary>
/// <param name="teamCityArtifactUri">The URI to the file in the build artifacts directory. Should be relative to the build artifacts directory.</param>
/// <param name="description">The file description. TeamCity shows both the ‘description’ and the filename of the referenced file. If a description was autogenerated, it is not shown.</param>
void WriteFile([NotNull] string teamCityArtifactUri, [NotNull] string description = "");

/// <summary>
/// Writes number as test metadata. Supported in TeamCity 2018.2+ https://confluence.jetbrains.com/display/TCD18/Reporting+Test+Metadata.
/// </summary>
/// <param name="value">The metadata value.</param>
/// <param name="name">The metadata name.</param>
void WriteValue([NotNull] double value, [NotNull] string name);

/// <summary>
/// Writes string value as test metadata. Supported in TeamCity 2018.2+ https://confluence.jetbrains.com/display/TCD18/Reporting+Test+Metadata.
/// </summary>
/// <param name="value">The metadata value.</param>
/// <param name="name">The metadata name.</param>
void WriteValue([NotNull] string value, [NotNull] string name);

/// <summary>
/// Writes link as test metadata. Supported in TeamCity 2018.2+ https://confluence.jetbrains.com/display/TCD18/Reporting+Test+Metadata.
/// </summary>
/// <param name="linkUri">The metadata URI.</param>
/// <param name="name">The metadata name.</param>
void WriteLink([NotNull] string linkUri, [NotNull] string name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ public virtual void Dispose()
public void PublishArtifact(string rules)
{
if (rules == null) throw new ArgumentNullException(nameof(rules));
CheckConsistency();
_artifactsWriter.PublishArtifact(rules);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,17 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special.Impl.Updater

/// <summary>
/// Service message updater that adds FlowId to service message according to
/// http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity
/// http://confluence.jetbrains.net/display/TCD18/Build+Script+Interaction+with+TeamCity
/// </summary>
public class FlowMessageUpdater : IServiceMessageUpdater
{
private readonly IFlowIdGenerator _flowId;

/// <summary>
/// Custructs updater
/// Constructs updater
/// </summary>
/// <param name="flowId">flowId set to all messages</param>
public FlowMessageUpdater([NotNull] string flowId)
{
if (flowId == null) throw new ArgumentNullException(nameof(flowId));
FlowId = flowId;
FlowId = flowId ?? throw new ArgumentNullException(nameof(flowId));
}

/// <summary>
Expand All @@ -42,16 +39,13 @@ public FlowMessageUpdater([NotNull] string flowId)
/// <param name="flowId"></param>
public FlowMessageUpdater([NotNull] IFlowIdGenerator flowId) : this(flowId.NewFlowId())
{
if (flowId == null) throw new ArgumentNullException(nameof(flowId));
_flowId = flowId;
}

public string FlowId { [NotNull] get; }

public IServiceMessage UpdateServiceMessage(IServiceMessage message)
{
if (message.DefaultValue != null) return message;
return new PatchedServiceMessage(message) {{"flowId", FlowId}};
return message.DefaultValue != null ? message : new PatchedServiceMessage(message) {{"flowId", FlowId}};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,15 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special.Impl.Updater

/// <summary>
/// Service message updater that adds Timestamp to service message according to
/// http://confluence.jetbrains.net/display/TCD7/Build+Script+Interaction+with+TeamCity
/// http://confluence.jetbrains.net/display/TCD18/Build+Script+Interaction+with+TeamCity
/// </summary>
public class TimestampUpdater : IServiceMessageUpdater
{
private readonly Func<DateTime> _timeService;

public TimestampUpdater([NotNull] Func<DateTime> timeService)
{
if (timeService == null) throw new ArgumentNullException(nameof(timeService));
_timeService = timeService;
_timeService = timeService ?? throw new ArgumentNullException(nameof(timeService));
}

public IServiceMessage UpdateServiceMessage(IServiceMessage message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,12 @@ public class TeamCityTestWriter : BaseDisposableWriter<IServiceMessageProcessor>
private readonly string _testName;
private TimeSpan? _duration;

public TeamCityTestWriter([NotNull] IServiceMessageProcessor target, [NotNull] string testName, [NotNull] IDisposable disposableHander)
: base(target, disposableHander)
public TeamCityTestWriter([NotNull] IServiceMessageProcessor target, [NotNull] string testName, [NotNull] IDisposable disposableHandler)
: base(target, disposableHandler)
{
if (target == null) throw new ArgumentNullException(nameof(target));
if (testName == null) throw new ArgumentNullException(nameof(testName));
if (disposableHander == null) throw new ArgumentNullException(nameof(disposableHander));
_testName = testName;
if (disposableHandler == null) throw new ArgumentNullException(nameof(disposableHandler));
_testName = testName ?? throw new ArgumentNullException(nameof(testName));
}

public void WriteStdOutput(string text)
Expand Down Expand Up @@ -70,6 +69,51 @@ public void WriteDuration(TimeSpan span)
_duration = span;
}

public void WriteImage(string teamCityArtifactUri, string description = "")
{
if (string.IsNullOrEmpty(teamCityArtifactUri)) throw new ArgumentException(nameof(teamCityArtifactUri));
if (description == null) throw new ArgumentNullException(nameof(description));
var message = new ServiceMessage("testMetadata") {{"testName", _testName}, {"type", "image"}, {"value", teamCityArtifactUri}};
if (!string.IsNullOrEmpty(description))
{
message.Add("name", description);
}

PostMessage(message);
}

public void WriteFile(string teamCityArtifactUri, string description = "")
{
if (string.IsNullOrEmpty(teamCityArtifactUri)) throw new ArgumentException(nameof(teamCityArtifactUri));
if (description == null) throw new ArgumentNullException(nameof(description));
var message = new ServiceMessage("testMetadata") {{"testName", _testName}, {"type", "artifact"}, {"value", teamCityArtifactUri}};
if (!string.IsNullOrEmpty(description))
{
message.Add("name", description);
}

PostMessage(message);
}

public void WriteValue(double value, string name)
{
if (string.IsNullOrEmpty(name)) throw new ArgumentException(nameof(name));
PostMessage(new ServiceMessage("testMetadata") {{"testName", _testName}, {"type", "number"}, {"value", value.ToString(CultureInfo.InvariantCulture)}, {"name", name}});
}

public void WriteValue(string value, string name)
{
if (string.IsNullOrEmpty(name)) throw new ArgumentException(nameof(name));
PostMessage(new ServiceMessage("testMetadata") {{"testName", _testName}, {"value", value}, {"name", name}});
}

public void WriteLink(string linkUri, string name)
{
if (string.IsNullOrEmpty(linkUri)) throw new ArgumentException(nameof(linkUri));
if (string.IsNullOrEmpty(name)) throw new ArgumentException(nameof(name));
PostMessage(new ServiceMessage("testMetadata") {{"testName", _testName}, {"type", "link"}, {"value", linkUri}, {"name", name}});
}

public void OpenTest()
{
PostMessage(new ServiceMessage("testStarted") {{"name", _testName}, {"captureStandardOutput", "false"}});
Expand Down

0 comments on commit 893d2d0

Please sign in to comment.