{"id":58695,"date":"2023-09-27T11:47:53","date_gmt":"2023-09-27T06:17:53","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=58695"},"modified":"2023-09-27T11:47:53","modified_gmt":"2023-09-27T06:17:53","slug":"playwright-nodejs-custom-reports-a-deep-dive-into-test-pass-fail-analytics-for-test-outcomes","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/playwright-nodejs-custom-reports-a-deep-dive-into-test-pass-fail-analytics-for-test-outcomes\/","title":{"rendered":"Playwright (Nodejs) Custom Reports: A Deep Dive into Test Pass\/Fail Analytics for Test Outcomes"},"content":{"rendered":"<p>We&#8217;ll explore Playwright with Node.js Custom Test Reports and, with the help of sample code, demonstrate how these reports can be your key to unlocking valuable insights from test results, ultimately enhancing the quality of your testing outcomes.<\/p>\n<h2><strong>Why Test Pass\/Fail Analytics Matter<br \/>\n<\/strong><\/h2>\n<p>Before we dive into the practical aspects, let&#8217;s understand the significance of test pass\/fail analytics. In automated testing, a test&#8217;s outcome is categorized as either &#8220;pass&#8221; (successful execution) or &#8220;fail&#8221; (an issue that occurred during execution and can be timeout or skipped ). These verdicts offer vital insights that drive software quality improvement.<\/p>\n<h2><strong>Introduction to Playwright Custom Reports<br \/>\n<\/strong><\/h2>\n<p>Playwright, a versatile and developer-friendly tool, provides custom reporting capabilities that allow you to extract and analyze test data in a structured manner. These reports are much more than just summaries; they are your secret weapon for informed decision-making.<\/p>\n<h2><strong>Key Features of Playwright Custom Reports<\/strong><\/h2>\n<p><strong><em>Detailed Test Logs:<\/em> <\/strong>Playwright custom reports offer exhaustive logs for every test run, pinpointing the exact step where a failure occurred.<br \/>\n<em><strong>Custom Metrics:<\/strong> <\/em>Define custom metrics relevant to your application to track specific key performance indicators (KPIs) during testing.<\/p>\n<h2><strong>Analysing Test Outcomes with Sample Code<\/strong><\/h2>\n<p>Let&#8217;s dive into the practical aspect of using Playwright Custom Reports with some sample code. We&#8217;ll outline a simple test scenario to demonstrate the power of these reports.<\/p>\n<blockquote>\n<pre>Create a js file with name - <em>'customerReportFilePath.js'\r\n<\/em>\r\n<em>\"use strict\";<\/em>\r\n<em>Object.defineProperty(exports, \"__esModule\", { value: true })<\/em>\r\n<em>import { writeFileSync } from \"fs\";<\/em>\r\n<em>var JSONSummaryReporter = \/** @class *\/ (function () {<\/em>\r\n<em>class JSONSummaryReporter {<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0constructor () {<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0this.executionDurationInMS = -1;<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0this.testStartedAt = 0;<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0this.passTests = [];<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0this.skipTests = [];<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0this.failTests = [];<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0this.interruptedTests = [];<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0this.timedOutTests = [];<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0this.testStatus = 'unknown';<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0this.warned = [];<\/em>\r\n<em>}<\/em>\r\n<em>onBegin() {<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0this.testStartedAt = Date.now();<\/em>\r\n<em>}<\/em>\r\n<em>onTestEnd(test, result) {<\/em>\r\n<em>\u00a0 \u00a0 \u00a0let testTitle = [];<\/em>\r\n<em>\u00a0 \u00a0 \u00a0let testFileName = [];<\/em>\r\n<em>\u00a0 \u00a0 \u00a0let clean = true;<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0for (let index = 0, a = test.titlePath(); index &lt; a.length; index++) {<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 let fileName = a[index];<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (fileName === '' &amp;&amp; clean)<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0continue;<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 clean = false;<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0testTitle.push(fileName);<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (fileName.includes('spec.js')) {<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 testFileName.push(fileName);<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0}<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0}<\/em>\r\n<em>\/\/ This will publish the file name + test title + status + + line number test begins on and column<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0let testDetails = \"\".concat(testFileName[0], \" : \").concat(test.title, \" : \", result.status, \" :\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\").concat(test.location.line, \" : \").concat(test.location.column)<\/em>\r\n<em>\/\/ Using the t variable in the push will push a full test test name + test description<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 let t = testTitle.join(' &gt; ');<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 let status = !['passed', 'skipped', 'interrupted'].includes(result.status) &amp;&amp; t.includes('@warn')<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 ? 'warned'<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 : result.status;<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 this[status].push(testDetails);<\/em>\r\n<em>\u00a0 }<\/em>\r\n<em>onEnd(result) {<\/em>\r\n<em>\u00a0 \u00a0 var _this = this;<\/em>\r\n<em>\u00a0 \u00a0 this.executionDurationInMS = Date.now() - this.testStartedAt;<\/em>\r\n<em>\u00a0 \u00a0 this.testStatus = result.status;<\/em>\r\n<em>\u00a0 \u00a0 \/\/ removing duplicate tests from pass tests array<\/em>\r\n<em>\u00a0 \u00a0 this.passTests = this.passTests.filter(function (element, index) {<\/em>\r\n<em>\u00a0 \u00a0 return _this.passTests.indexOf(element) === index;<\/em>\r\n<em>});<\/em>\r\n<em>\/\/ removing duplicate and flakey (pass on a retry) tests from the fail tests array<\/em>\r\n<em>\u00a0 \u00a0this.failTests = this.failTests.filter(function (element, index) {<\/em>\r\n<em>\u00a0 \u00a0 \u00a0if (!_this.passTests.includes(element))<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 return _this.failTests.indexOf(element) === index;<\/em>\r\n<em>\u00a0 \u00a0 \u00a0});<\/em>\r\n<em>\u00a0 \u00a0 \u00a0writeFileSync(`.\/summary.json`, JSON.stringify(this, null, ' '));<\/em>\r\n<em>\u00a0 \u00a0 }<\/em>\r\n<em>\u00a0 }<\/em>\r\n<em>\u00a0 \u00a0return JSONSummaryReporter;<\/em>\r\n<em>}());<\/em>\r\n<em>const _default = JSONSummaryReporter;<\/em>\r\n<em>export { _default as default };<\/em><\/pre>\n<\/blockquote>\n<p><strong>In playright.config file add below line of code\u00a0 :<\/strong><\/p>\n<pre>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0<em>reporter :['.\/customerReportFilepath.js'] \/\/ js file path\u00a0<\/em><\/pre>\n<p>Once the test execution ends, it will generate a json file <strong><em>\u2018summary.json\u2019<\/em><\/strong> with the execution results, test pass\/fail, and execution duration analytics. Similarly, we can get more test details based on the application requirements.<\/p>\n<blockquote>\n<pre><strong>Result in 'summary.json' file :\r\n<\/strong>\r\n<em>{<\/em>\r\n<em>\u00a0 \u00a0 \u00a0\"executionDurationInMS\": 4157,<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \"passTests\": [<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \"DemoPassTest.spec.js : Demo test : passed : 20 : 9\"<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0],<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \"skipTests\": [<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0],<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0\"failTests\": [<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \"DemoFailTest.spec.js : Demo Fail test : failed : 10 : 5\"<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 ],<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0\"interruptedTests\": [<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 ],<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \"warned\": [],<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \"timedOutTests\": [],<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \"testStatus\": \"failed\",<\/em>\r\n<em>\u00a0 \u00a0 \u00a0 \u00a0 \"testStartedAt\": 169467477831<\/em>\r\n<em>\u00a0 \u00a0 \u00a0}<\/em><\/pre>\n<\/blockquote>\n<h2><strong>Conclusion<br \/>\n<\/strong><\/h2>\n<p>Playwright Custom Reports provides test outcomes of automated testing. They illuminate the path to test pass\/fail insights, helping you navigate toward enhanced testing results. By grasping the importance of test execution analytics and harnessing the capabilities of Playwright Custom Reports, you can elevate your testing strategy.<\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>We&#8217;ll explore Playwright with Node.js Custom Test Reports and, with the help of sample code, demonstrate how these reports can be your key to unlocking valuable insights from test results, ultimately enhancing the quality of your testing outcomes. Why Test Pass\/Fail Analytics Matter Before we dive into the practical aspects, let&#8217;s understand the significance of [&hellip;]<\/p>\n","protected":false},"author":1645,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":69},"categories":[1818,1185],"tags":[4941,5464],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58695"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1645"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=58695"}],"version-history":[{"count":2,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58695\/revisions"}],"predecessor-version":[{"id":58760,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58695\/revisions\/58760"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=58695"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=58695"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=58695"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}