Skip to content

Commit b1672b4

Browse files
committed
Merged PR 1536: 1.0.7500.0 release
2 parents 5496c8b + 9ecb8db commit b1672b4

File tree

6 files changed

+98
-222
lines changed

6 files changed

+98
-222
lines changed

pipelines/azure-pipelines.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trigger: none
2+
3+
jobs:
4+
- job:
5+
displayName: Verify Pull Requests
6+
pool:
7+
name: TestSuiteBuildPool
8+
workspace:
9+
clean: false
10+
timeoutInMinutes: 0
11+
12+
steps:
13+
- task: BatchScript@1
14+
displayName: 'Build ProtocolTestFramework'
15+
inputs:
16+
filename: 'src/build.cmd'

src/SharedAssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55

66
[assembly: AssemblyCompany("Microsoft")]
77
[assembly: AssemblyProduct("Protocol Test Framework")]
8-
[assembly: AssemblyVersion("1.0.7000.0")]
8+
[assembly: AssemblyVersion("1.0.7500.0")]

src/htmltestlogger/DataType.cs

Lines changed: 15 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33

44
using System;
55
using System.Collections.Generic;
6-
using System.Linq;
7-
using System.Text;
8-
using System.Threading.Tasks;
96

107
namespace Microsoft.Protocols.TestTools
118
{
@@ -107,6 +104,16 @@ public class TestCaseDetail
107104
/// </summary>
108105
public string Source;
109106

107+
/// <summary>
108+
/// The test class of the test case
109+
/// </summary>
110+
public string ClassType;
111+
112+
/// <summary>
113+
/// The Categories of the test case
114+
/// </summary>
115+
public List<string> Categories;
116+
110117
/// <summary>
111118
/// The ErrorStackTrace log of the test case
112119
/// </summary>
@@ -140,65 +147,23 @@ public class TestCaseDetail
140147
/// <param name="endTime">End time of the test case</param>
141148
/// <param name="result">Result of the test case</param>
142149
/// <param name="source">Assembly of the test case</param>
143-
public TestCaseDetail(string name, DateTimeOffset startTime, DateTimeOffset endTime, string result, string source)
150+
/// <param name="classType">Class of the test case</param>
151+
/// <param name="categories">Categories of the test case</param>
152+
public TestCaseDetail(string name, DateTimeOffset startTime, DateTimeOffset endTime, string result, string source, string classType, List<string> categories)
144153
{
145154
this.Name = name;
146155
this.StartTime = startTime;
147156
this.EndTime = endTime;
148157
this.Result = result;
149158
this.Source = source;
159+
this.ClassType = classType;
160+
this.Categories = categories;
150161
this.ErrorStackTrace = new List<string>();
151162
this.ErrorMessage = new List<string>();
152163
this.StandardOut = new List<StandardOutDetail>();
153164
this.StandardOutTypes = new List<string>();
154165
this.CapturePath = null;
155166
}
156167
}
157-
158-
/// <summary>
159-
/// Represents the summary for all test cases
160-
/// </summary>
161-
public class RunSummary
162-
{
163-
/// <summary>
164-
/// The number of total test cases
165-
/// </summary>
166-
public long TotalCount;
167-
168-
/// <summary>
169-
/// The number of passed test cases
170-
/// </summary>
171-
public long PassedCount;
172-
173-
/// <summary>
174-
/// The number of failed test cases
175-
/// </summary>
176-
public long FailedCount;
177-
178-
/// <summary>
179-
/// The number of inconclusive test cases
180-
/// </summary>
181-
public long InconclusiveCount;
182-
183-
/// <summary>
184-
/// The pass rate of this run
185-
/// </summary>
186-
public float PassRate;
187-
188-
/// <summary>
189-
/// The start time of this run
190-
/// </summary>
191-
public string StartTime;
192-
193-
/// <summary>
194-
/// The end time to of this run
195-
/// </summary>
196-
public string EndTime;
197-
198-
/// <summary>
199-
/// The duration of this run
200-
/// </summary>
201-
public string Duration;
202-
}
203168
}
204169
}

src/htmltestlogger/HtmlTestLogger.cs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System;
5+
using System.Collections.Concurrent;
56
using System.Collections.Generic;
67
using System.IO;
78
using System.Linq;
89
using System.Text;
910
using System.Text.RegularExpressions;
10-
using System.Threading.Tasks;
11-
using Microsoft.Win32;
1211
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
1312
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
1413
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
@@ -29,9 +28,11 @@ public class HtmlTestLogger : ITestLoggerWithParameters
2928
private DateTimeOffset testRunEndTime = DateTimeOffset.MinValue.ToLocalTime(); //The end time of the test run
3029
private TxtToJSON txtToJSON = new TxtToJSON();
3130

31+
private ConcurrentDictionary<string, DataType.TestCaseDetail> results = new ConcurrentDictionary<string, DataType.TestCaseDetail>(); //All the test results
32+
33+
private const string categoryPropertyKey = "MSTestDiscoverer.TestCategory";
3234
private const string scriptNode = "<script language=\"javascript\" type=\"text/javascript\">";
3335
private const string jsFileName_Functions = "functions.js";
34-
private const string jsFileName_Jquery = "jquery-1.11.0.min.js";
3536
private const string indexHtmlName = "index.html";
3637
private const string txtResultFolderName = "Txt";
3738
private const string htmlResultFolderName = "Html";
@@ -123,6 +124,7 @@ private void TestResultHandler(object sender, TestResultEventArgs e)
123124
}
124125

125126
DataType.TestCaseDetail caseDetail = ConvertToTestCase(e.Result);
127+
results.TryAdd(caseDetail.Name, caseDetail);
126128

127129
// Generate txt log file
128130
string txtFileName = Path.Combine(
@@ -196,10 +198,13 @@ private void CreateReportFolder()
196198
private DataType.TestCaseDetail ConvertToTestCase(TestResult result)
197199
{
198200
var eolSeparators = new char[] { '\r', '\n' };
199-
string caseName = !string.IsNullOrEmpty(result.DisplayName) ? result.DisplayName : result.TestCase.FullyQualifiedName.Split('.').Last();
201+
202+
string caseName = !string.IsNullOrEmpty(result.TestCase.DisplayName) ? result.TestCase.DisplayName : result.TestCase.FullyQualifiedName.Split('.').Last();
200203
string outcome = result.Outcome == TestOutcome.Skipped ? "Inconclusive" : result.Outcome.ToString();
204+
string classType = result.TestCase.FullyQualifiedName.Split('.').Reverse().ElementAtOrDefault(1);
205+
List<string> testCategories = GetCustomPropertyValueFromTestCase(result.TestCase, categoryPropertyKey);
201206

202-
var ret = new DataType.TestCaseDetail(caseName, result.StartTime, result.EndTime, outcome, result.TestCase.Source);
207+
var ret = new DataType.TestCaseDetail(caseName, result.StartTime, result.EndTime, outcome, result.TestCase.Source, classType, testCategories);
203208

204209
if (!String.IsNullOrEmpty(result.ErrorStackTrace))
205210
{
@@ -257,6 +262,32 @@ private DataType.TestCaseDetail ConvertToTestCase(TestResult result)
257262
return ret;
258263
}
259264

265+
/// <summary>
266+
/// Get Custom property values from test cases.
267+
/// </summary>
268+
/// <param name="testCase">TestCase object extracted from the TestResult</param>
269+
/// <param name="categoryID">Property Name from the list of properties in TestCase</param>
270+
/// <returns> list of properties</returns>
271+
public List<string> GetCustomPropertyValueFromTestCase(TestCase testCase, string categoryID)
272+
{
273+
var customProperty = testCase.Properties.FirstOrDefault(t => t.Id.Equals(categoryID));
274+
275+
if (customProperty != null)
276+
{
277+
var cateogryValues = (string[])testCase.GetPropertyValue(customProperty);
278+
if (cateogryValues != null)
279+
{
280+
return cateogryValues.ToList();
281+
}
282+
else
283+
{
284+
return Enumerable.Empty<String>().ToList();
285+
}
286+
}
287+
288+
return Enumerable.Empty<String>().ToList();
289+
}
290+
260291
/// <summary>
261292
/// Inserts the corresponding script to the template html and generates the [testcase].html
262293
/// </summary>
@@ -314,10 +345,8 @@ private string ConstructListAndSummaryObj(TestRunCompleteEventArgs e)
314345
{
315346
StringBuilder sb = new StringBuilder();
316347
sb.AppendLine();
317-
sb.AppendLine("var listObj = " + txtToJSON.TestCasesString(txtResultFolderPath, captureFolderPath) + ";");
348+
sb.AppendLine("var listObj = " + txtToJSON.TestCasesString(txtResultFolderPath, captureFolderPath, results) + ";");
318349

319-
// Clean the temp file
320-
File.Delete(txtToJSON.CaseCategoryFile);
321350
return sb.ToString();
322351
}
323352

src/htmltestlogger/Resources/functions.js

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,11 @@ function ShowSummary()
302302
var passedCount = listObj.TestCases.filter(function (tc) { return tc.Result === "Passed" }).length;
303303
var failedCount = listObj.TestCases.filter(function (tc) { return tc.Result === "Failed" }).length;
304304
var inconclusiveCount = listObj.TestCases.filter(function (tc) { return tc.Result === "Inconclusive" }).length;
305-
var passRate = (totalCount === 0 ? 0 : passedCount / totalCount).toFixed(2);
305+
var passRate = (totalCount === 0 ? 0 : passedCount / totalCount * 100).toFixed(2);
306306

307307
var tbody = document.getElementById("tableid");
308308
var newrow = tbody.insertRow(-1);
309-
309+
310310
CreateText(newrow.insertCell(0), totalCount);
311311
CreateText(newrow.insertCell(1), passedCount);
312312
CreateText(newrow.insertCell(2), failedCount);
@@ -489,12 +489,12 @@ function ShowDetail(caseDetail, logTypes)
489489
{
490490
if (detailObj[caseDetail][j]['Type'].toLowerCase().indexOf('succee') != -1
491491
|| detailObj[caseDetail][j]['Type'].toLowerCase().indexOf('passed') != -1)
492-
html += "<p style=\"background-color:rgb(0,255,0)\">" + detailObj[caseDetail][j]['Content'];
492+
html += "<p style=\"background-color:rgb(0,255,0)\">" + escapeHtml(detailObj[caseDetail][j]['Content']);
493493
else if (detailObj[caseDetail][j]['Type'] == 'TestStep')
494-
html += "<p style=\"background-color:rgb(0,255,255)\">" + detailObj[caseDetail][j]['Content'];
494+
html += "<p style=\"background-color:rgb(0,255,255)\">" + escapeHtml(detailObj[caseDetail][j]['Content']);
495495
else if (detailObj[caseDetail][j]['Type'].toLowerCase().indexOf('failed') != -1)
496-
html += "<p style=\"background-color:red;color:white\">" + detailObj[caseDetail][j]['Content'];
497-
else html += "<p>" + detailObj[caseDetail][j]['Content'];
496+
html += "<p style=\"background-color:red;color:white\">" + escapeHtml(detailObj[caseDetail][j]['Content']);
497+
else html += "<p>" + escapeHtml(detailObj[caseDetail][j]['Content']);
498498
}
499499
}
500500
html += html == "" ? "" : "</p>";
@@ -507,7 +507,7 @@ function ShowDetail(caseDetail, logTypes)
507507
var html = '';
508508
len = detailObj[caseDetail].length;
509509
for (var j = 0; j < len; j++)
510-
html += "<p>" + detailObj[caseDetail][j];
510+
html += "<p>" + escapeHtml(detailObj[caseDetail][j]);
511511
html += html == "" ? "" : "</p>";
512512
document.getElementById("ttrace").style.display = html == "" ? 'none' : '';
513513
document.getElementById("AfterErrorStackTrace").style.display = html == "" ? 'none' : '';
@@ -517,7 +517,7 @@ function ShowDetail(caseDetail, logTypes)
517517
var html = '';
518518
len = detailObj[caseDetail].length;
519519
for (var j = 0; j < len; j++)
520-
html += "<p>" + detailObj[caseDetail][j];
520+
html += "<p>" + escapeHtml(detailObj[caseDetail][j]);
521521
html += html == "" ? "" : "</p>";
522522
document.getElementById("tmsg").style.display = html == "" ? 'none' : '';
523523
document.getElementById("AfterErrorMessage").style.display = html == "" ? 'none' : '';
@@ -660,3 +660,13 @@ function FilterLog(obj)
660660
}
661661
ShowDetail('StandardOut', logTypes);
662662
}
663+
664+
// Escape html special characters
665+
function escapeHtml(text) {
666+
return text
667+
.replace(/&/g, "&amp;")
668+
.replace(/</g, "&lt;")
669+
.replace(/>/g, "&gt;")
670+
.replace(/"/g, "&quot;")
671+
.replace(/'/g, "&#039;");
672+
}

0 commit comments

Comments
 (0)