tools/traceabilitytool/traceability_tool/reportwriter.cs (179 lines of code) (raw):
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Text; // Used for StringBuilder class
using System.IO; // Used for TextWriter and StreamWriter class.
using System; // Used for Exception class.
using System.Windows.Forms; // Used for MessageBox class
namespace TraceabilityTool
{
class ReportWriter
{
// This class is responsible for writing reports generated by ReportGenerator class to plain text files.
public static void WriteTraceabilityReport(string outputFolderPath)
{
StringBuilder sb = new StringBuilder();
foreach (string key in ReportGenerator.reqDocLookup.Keys)
{
// Print requirement ID.
sb.AppendLine(key);
// Print the path of the document where the requirement was defined.
sb.AppendLine(" Defined in: " + ReportGenerator.reqDocLookup[key]);
// Print source code file paths
bool firstLine = true;
if (ReportGenerator.reqCodeMatrix.ContainsKey(key))
{
foreach (FilePathLineNum reqData in ReportGenerator.reqCodeMatrix[key])
{
if (firstLine)
{
sb.AppendLine(" Coded in: " + reqData.filePath + ", line " + reqData.lineNum.ToString());
firstLine = false;
}
else
{
sb.AppendLine(" " + reqData.filePath + ", line " + reqData.lineNum.ToString());
}
}
}
else
{
sb.AppendLine(" Not Coded");
}
// Print test code file paths
if (ReportGenerator.reqTestMatrix.ContainsKey(key))
{
firstLine = true;
foreach (FilePathLineNum reqData in ReportGenerator.reqTestMatrix[key])
{
if (firstLine)
{
sb.AppendLine(" Tested in: " + reqData.filePath + ", line " + reqData.lineNum.ToString());
firstLine = false;
}
else
{
sb.AppendLine(" " + reqData.filePath + ", line " + reqData.lineNum.ToString());
}
}
}
else
{
sb.AppendLine(" Not Tested");
}
}
// Print totals
sb.AppendLine("".PadRight(42, '='));
sb.AppendLine("Total unique requirements : " + ReportGenerator.reqDocLookup.Count.ToString());
sb.AppendLine("Total implemented requirements : " + ReportGenerator.reqCodeMatrix.Count.ToString());
sb.AppendLine("Total tested requirements : " + ReportGenerator.reqTestMatrix.Count.ToString());
sb.AppendLine("Total unimplemented requirements: " + ReportGenerator.missingCodeCoverage.Count.ToString());
sb.AppendLine("Total untested requirements : " + ReportGenerator.missingTestCoverage.Count.ToString());
// Output data to a CSV file.
writeStringToFile(sb.ToString(), outputFolderPath + @"\traceability_matrix.txt");
}
public static void WriteInvalidReqReport(string outputFolderPath)
{
int maxKeyWidth = ReportGenerator.invalidRequirements.maxKeyLength + 3;
int maxReasonWidth = ReportGenerator.invalidRequirements.maxReasonLength + 3;
StringBuilder sb = new StringBuilder();
foreach (string key in ReportGenerator.invalidRequirements.Keys)
{
sb.Append(key.PadRight(maxKeyWidth));
bool newLine = false;
foreach (InvalidReqDictEntry entry in ReportGenerator.invalidRequirements[key])
{
if (newLine)
{
sb.AppendLine("".PadRight(maxKeyWidth) + entry.reason.PadRight(maxReasonWidth) + entry.filePath + ", line " + entry.lineNum.ToString());
}
else
{
sb.AppendLine(entry.reason.PadRight(maxReasonWidth) + entry.filePath + ", line " + entry.lineNum.ToString());
newLine = true;
}
}
}
sb.AppendLine("".PadRight(35, '='));
sb.AppendLine("Total invalid requirements: " + ReportGenerator.invalidRequirements.Count.ToString());
// Output data to a CSV file.
writeStringToFile(sb.ToString(), outputFolderPath + @"\invalid_requirements.txt");
}
public static void WriteMissingCodeCoverageReport(string outputFolderPath)
{
StringBuilder sb = new StringBuilder();
foreach (string key in ReportGenerator.missingCodeCoverage.Keys)
{
sb.AppendLine(key.PadRight(ReportGenerator.missingCodeCoverageKeyWidth + 3) + ReportGenerator.missingCodeCoverage[key]);
}
sb.AppendLine("".PadRight(41, '='));
sb.AppendLine("Total unimplemented requirements: " + ReportGenerator.missingCodeCoverage.Count.ToString());
// Output data to a CSV file.
writeStringToFile(sb.ToString(), outputFolderPath + @"\missing_code_coverage.txt");
}
public static void WriteMissingTestCoverageReport(string outputFolderPath)
{
StringBuilder sb = new StringBuilder();
foreach (string key in ReportGenerator.missingTestCoverage.Keys)
{
sb.AppendLine(key.PadRight(ReportGenerator.missingTestCoverageKeyWidth + 3) + ReportGenerator.missingTestCoverage[key]);
}
sb.AppendLine("".PadRight(35, '='));
sb.AppendLine("Total untested requirements: " + ReportGenerator.missingTestCoverage.Count.ToString());
// Output data to a CSV file.
writeStringToFile(sb.ToString(), outputFolderPath + @"\missing_test_coverage.txt");
}
public static void WriteMissingCodeAndTestCoverageReport(string outputFolderPath)
{
int count = 0;
int maxKeyWidth = ReportGenerator.missingTestCoverageKeyWidth;
StringBuilder sb = new StringBuilder();
// Pick the shorter of the key lengths from missing code and test coverage lists
// (if a longer key is not found on both lists at the same time, it will not be output to the report).
if (ReportGenerator.missingCodeCoverageKeyWidth < maxKeyWidth)
maxKeyWidth = ReportGenerator.missingCodeCoverageKeyWidth;
foreach (string key in ReportGenerator.missingTestCoverage.Keys)
{
if (ReportGenerator.missingCodeCoverage.ContainsKey(key))
{
sb.AppendLine(key.PadRight(maxKeyWidth + 3) + ReportGenerator.missingTestCoverage[key]);
count++;
}
}
sb.AppendLine("".PadRight(75, '='));
sb.AppendLine("Total number of requirements missing both implementation and tests: " + count.ToString());
// Output data to a CSV file.
writeStringToFile(sb.ToString(), outputFolderPath + @"\missing_code_and_test_coverage.txt");
}
public static void WriteRepeatingReqReport(string outputFolderPath)
{
StringBuilder sb = new StringBuilder();
foreach (string key in ReportGenerator.repeatingRequirements.Keys)
{
sb.Append(key.PadRight(ReportGenerator.repeatingRequirementsKeyWidth + 3));
bool newLine = false;
foreach (string reqDocPath in ReportGenerator.repeatingRequirements[key])
{
if (newLine)
{
sb.AppendLine("".PadRight(ReportGenerator.repeatingRequirementsKeyWidth + 3) + reqDocPath);
}
else
{
sb.AppendLine(reqDocPath);
newLine = true;
}
}
}
sb.AppendLine("".PadRight(35, '='));
sb.AppendLine("Total repeating requirements: " + ReportGenerator.repeatingRequirements.Count.ToString());
// Output data to a CSV file.
writeStringToFile(sb.ToString(), outputFolderPath + @"\repeating_requirements.txt");
}
public static void writeStringToFile(string str, string outputFile)
{
try
{
TextWriter outfile = new StreamWriter(outputFile);
{
outfile.Write(str);
outfile.Close();
}
}
catch (Exception exception)
{
string message = "An error occurred while attempting to access the file " + outputFile + System.Environment.NewLine +
exception.Message + System.Environment.NewLine;
if (ReportGenerator.useGUI)
MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
else
Console.WriteLine(message);
Program.exitCode = 1;
}
}
}
}