// // Copyright © 2018 Ranorex All rights reserved // using System; using System.IO; using Ranorex.AutomationHelpers.UserCodeCollections; using Ranorex.Core.Reporting; using Ranorex.Core.Testing; namespace Ranorex.AutomationHelpers.Modules { /// /// Allows conversion of the default Ranorex report to PDF. /// [TestModule("FFA0759D-37D2-4ABB-89A7-411F0FCF2DFE", ModuleType.UserCode, 1)] public sealed class ReportToPDFModule : ITestModule { //Variables private static string lastTestSuiteLogged; private System.DateTime testSuiteCompleted; /// /// Constructs a new instance. /// public ReportToPDFModule() { //Init variables this.registered = false; this.PdfName = ""; this.Xml = ""; //Possible values: none | failed | all this.Details = "all"; } private bool registered { get; set; } private DirectoryInfo ZippedReportFileDirectoryInfo { get; set; } [TestVariable("1d09c6b5-db7a-4ed0-a13c-ee2add5d3d37")] public string PdfName { get; set; } [TestVariable("536f8a69-f246-4f2b-ae9e-1f62babb2ba9")] public string PdfDirectoryPath { get; set; } [TestVariable("c15f25ea-9409-4e1a-b76e-cd208bae6c56")] public string Xml { get; set; } [TestVariable("b9993b89-d8cb-45fe-829b-42b0f8dd8a00")] public string Details { get; set; } #if !RX72 && !RX80 //this requires Ranorex 8.1+ [TestVariable("7f788c18-962c-41ab-b591-9c3122512c5e")] public bool DeleteRanorexReport { get; set; } #endif /// /// Converts the Ranorex Report into PDF after the test run completed. Use this module in /// the TearDown of your TestCase to ensure that it is executed even on failing test runs. /// /// You should not call this method directly, instead pass the module /// instance to the method /// that will in turn invoke this method. void ITestModule.Run() { //Delegate must be registered only once if (!this.registered) { this.testSuiteCompleted = new System.DateTime(); //PDF will be generated at the very end of the TestSuite TestSuite.TestSuiteCompleted += CreatePdfReportDelegate; #if !RX72 && !RX80 //this requires Ranorex 8.1+ if (this.DeleteRanorexReport) { TestSuiteRunner.TestRunCompleted += delegate { var cleaner = new CleanupRanorexReport(this.testSuiteCompleted); cleaner.Cleanup(); }; } #endif this.registered = true; } } public string CreatePDF() { //Specify Ranorex Report name if not already set if (String.IsNullOrEmpty(this.PdfName)) { this.PdfName = CreatePDFName(); } var pdfReportFilePath = ""; try { pdfReportFilePath = CreatePdfReportPath(this.PdfName, this.PdfDirectoryPath); var relativePdfReportPath = ConvertReportToPDF(pdfReportFilePath, this.Xml, this.Details); Report.LogHtml( ReportLevel.Success, "PDFReport", string.Format( "Successfully created PDF: Open PDF", relativePdfReportPath)); } catch (Exception e) { Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("ReportToPDF: " + e.Message); Console.ResetColor(); } //Delete *.rxzlog if not enabled within test suite settings Cleanup(); //Update error value UpdateError(); return pdfReportFilePath; } private void CreatePdfReportDelegate(object sender, EventArgs e) { this.testSuiteCompleted = System.DateTime.Now; var currentTestSuiteName = TestSuite.Current.Name; //Prevent redundant PDF conversion - required for multi test suite run if (ReportToPDFModule.lastTestSuiteLogged != currentTestSuiteName) { CreatePDF(); ReportToPDFModule.lastTestSuiteLogged = currentTestSuiteName; } TestSuite.TestSuiteCompleted -= CreatePdfReportDelegate; } private string ConvertReportToPDF(string pdfReportPath, string xml, string details) { var zippedReportFileDirectory = CreateTempReportFileDirectory(); var name = TestReport.ReportEnvironment.ReportName; var input = String.Format(@"{0}\{1}.rxzlog", zippedReportFileDirectory, name); FinishReport(); Report.Zip(TestReport.ReportEnvironment, zippedReportFileDirectory, name); Report.Info(Directory.GetCurrentDirectory()); // foreach (var fl in Directory.GetFiles(Directory.GetCurrentDirectory(), "*", SearchOption.AllDirectories)) { // Report.Info(fl.ToString()); // } //Report.Info(Directory.GetFiles(Directory.GetCurrentDirectory()).ToString()); Ranorex.PDF.Creator.CreatePDF(input, pdfReportPath, xml, details); return GeneratePathToPdfRelativeToReport(pdfReportPath); } private static string CreatePdfReportPath(string pdfName, string pdfDirectoryPath) { var reportFileDirectory = string.IsNullOrEmpty(pdfDirectoryPath) ? TestReport.ReportEnvironment.ReportFileDirectory : pdfDirectoryPath; var PDFReportFilePath = String.Format(@"{0}\{1}", reportFileDirectory, AddPdfExtension(pdfName)); return PDFReportFilePath; } private static string AddPdfExtension(string pdfName) { return pdfName.EndsWith(".pdf") ? pdfName : pdfName + ".pdf"; } private static string GeneratePathToPdfRelativeToReport(string currentPdfPath) { var pdfUri = new Uri(currentPdfPath, UriKind.RelativeOrAbsolute); if (!pdfUri.IsAbsoluteUri) { // if the path is relative, its relative to the execution, not report var currentExeUri = new Uri(Environment.CurrentDirectory + "\\"); pdfUri = new Uri(currentExeUri, pdfUri); } return Utils.CreateRelativePath(TestReport.ReportEnvironment.ReportDataFilePath, pdfUri.AbsoluteUri); } private void FinishReport() { Activity activity = ActivityStack.Current ; //Necessary to end the Ranorex Report in order to update the duration and finalize the status if (activity.GetType().Name.Equals("TestSuiteActivity")) { TestReport.EndTestModule(); Report.End(); } TestReport.SaveReport(); } private string CreateTempReportFileDirectory() { //Create new temp directory for zipped Report try { this.ZippedReportFileDirectoryInfo = Directory.CreateDirectory( string.Format(@"{0}\temp", TestReport.ReportEnvironment.ReportFileDirectory)); return this.ZippedReportFileDirectoryInfo.FullName; } catch (Exception ex) { throw new InvalidOperationException("Failed to create temp folder: " + ex.Message); } } private void Cleanup() { try { this.ZippedReportFileDirectoryInfo.Delete(true); } catch (Exception ex) { throw new InvalidOperationException("Failed to recursively delete zipped report file directory: " + ex.Message); } } private static string CreatePDFName() { //Report status is not part of the Report name at this stage of the test var name = TestReport.ReportEnvironment.ReportName; //Get status from TestSuite var testsuite = (TestSuite)TestSuite.Current; if (testsuite.ReportSettings.ReportFormatString.Contains("%X")) { name += "_" + GetTestSuiteStatus(); } return name; } private static void UpdateError() { if (GetTestSuiteStatus().Contains("Failed")) { Report.Failure("Rethrow Exception within PDF Module (Necessary for correct error value)"); } } private static string GetTestSuiteStatus() { string status = ""; var rootChildren = ActivityStack.Instance.RootActivity.Children; if (rootChildren.Count > 1) { Console.WriteLine("Multiple TestSuiteActivites, status taken from first entry"); } var testSuiteAct = rootChildren[0] as TestSuiteActivity; if (testSuiteAct != null) { status = testSuiteAct.Status.ToString(); } return status; } } internal sealed class CleanupRanorexReport { private readonly System.DateTime testSuiteCompleted; internal CleanupRanorexReport(System.DateTime testSuiteCompleted) { this.testSuiteCompleted = testSuiteCompleted; } /// /// Used to cleanup and delete all Ranorex report related files from current testrun /// internal void Cleanup() { try { var reportFileDirectory = TestReport.ReportEnvironment.ReportFileDirectory; var name = TestReport.ReportEnvironment.ReportName; var reportDataFile = TestReport.ReportEnvironment.ReportDataFilePath; var reportFile = string.Format(@"{0}\{1}.{2}", reportFileDirectory, name, GetReportExtension()); DeleteReportImages(); File.Delete(reportDataFile); File.Delete(reportFile); } catch (Exception ex) { throw new InvalidOperationException("Failed to delete Ranorex report files: " + ex.Message); } } private void DeleteReportImages() { #pragma warning disable 0618 //Check if images are stored within a subdirectory - default if (TestReport.ReportEnvironment.UseScreenshotFolder) #pragma warning restore 0618 { var imageFolderDirectoryInfo = new DirectoryInfo(TestReport.ReportEnvironment.ReportScreenshotFolderPath); if (imageFolderDirectoryInfo.Exists) { imageFolderDirectoryInfo.Delete(true); } } //Delete image files, which match the report short name and aren't older then currently created report else { const int MaxPrefixLen = 8; var shortName = TestReport.ReportEnvironment.ReportName.Substring(0, Math.Min(TestReport.ReportEnvironment.ReportName.Length, MaxPrefixLen)); var imageFolderDirectoryInfo = new DirectoryInfo(TestReport.ReportEnvironment.ReportScreenshotFolderPath); if (imageFolderDirectoryInfo.Exists) { foreach (var image in imageFolderDirectoryInfo.GetFiles(string.Format("*{0}*.jpg", shortName))) { var imageCreationTime = File.GetCreationTime(image.FullName); if (testSuiteCompleted < imageCreationTime.AddSeconds(10)) //Added 10 secs to the imageCreationTime to ensure the images are actually created { image.Delete(); } } } } } private string GetReportExtension() { var extension = TestReport.ReportEnvironment.ReportDataFilePath.Split('.'); return extension[extension.Length - 2]; } } }