kudobuilder / kuttl

KUbernetes Test TooL (kuttl)
https://kuttl.dev
Apache License 2.0
636 stars 83 forks source link

Increase granularity of JUnit reports. #509

Closed porridge closed 2 months ago

porridge commented 3 months ago

What

Change the report schema.

Previously:

<testsuites> (everything)
  <testsuite> (directory of tests)
   <testcase> (a test directory containing steps)

Now:

<testsuites> (everything)
  <testsuite> (directory of tests)
   <testsuite> (a test directory containing steps)
     <testcase> (a single step)

See example at the bottom.

Why

Improved automation

The primary driver for this change is increasing quality of bug reports that are filed by automation based on the JUnit report files by junit2jira.

The tests in the stackrox suite are rather heavyweight, because the operands under test are heavyweight - resource-hungry and slow to set up. This means each test consists of a rather long series of steps - each making assertions after flipping a certain feature on or off.

However this means that each test can fail for a variety of mostly unrelated reasons.

One important thing to understand is how junit2jira coalesces reports. It treats the concatenation of <testcase>'s classname and name attributes as the key (title) for tickets. Once its detects a ticket with the same title already exists, then it appends a comment to this existing ticket, rather than create a new one.

However given the above, this leads to ever-growing tickets with just vaguely related failure root causes (after a while).

Changing the report to map each <testcase> to a kuttl step, rather than whole test, is going to make these automated reports more meaningful and easier to deal with.

More detailed time data

An additional advantage is the more granular timing data - shows which steps are the slow ones.

Caveats

While it seems that nested <testsuite> elements are widely accepted as valid ([1], [2] not all JUnit parsing tools might support this out of the box, so there is some potential for breaking existing workflows.

FWIW, so far there were no comments on slack about this change, so perhaps there are not many report users.

If needed, I could add a knob to make this high-granularity opt-in.

Example

Before:

<testsuites name="" tests="4" failures="0" time="843.243">
  <testsuite tests="2" failures="0" timestamp="2024-03-06T13:03:26.798769149Z" time="829.547" name="./tests/central">
    <testcase classname="central" name="central-misc" timestamp="2024-03-06T13:03:26.844298978Z" time="708.114" assertions="142"/>
    <testcase classname="central" name="central-basic" timestamp="2024-03-06T13:03:26.833004446Z" time="829.513" assertions="117"/>
  </testsuite>
  <testsuite tests="1" failures="0" timestamp="2024-03-06T13:03:26.798868492Z" time="11.064" name="./tests/controller">
    <testcase classname="controller" name="metrics" timestamp="2024-03-06T13:03:26.808993539Z" time="11.054" assertions="4"/>
  </testsuite>
  <testsuite tests="1" failures="0" timestamp="2024-03-06T13:03:26.798915549Z" time="742.563" name="./tests/securedcluster">
    <testcase classname="securedcluster" name="sc-basic" timestamp="2024-03-06T13:03:26.832535251Z" time="742.529" assertions="120"/>
  </testsuite>
</testsuites>

After:

 <testsuites name="" tests="38" failures="3" time="1464.084">
   <testsuite tests="25" failures="1" timestamp="2024-03-14T10:27:42.483185024+01:00" time="1462.059" name="./tests/central">
     <testsuite tests="10" failures="1" timestamp="2024-03-14T10:27:42.494834755+01:00" time="1462.047" name="central-basic">
       <testcase classname="central-basic" name="setup" timestamp="2024-03-14T10:27:42.49483545+01:00" time="0.358" assertions="0"></testcase>
       <testcase classname="central-basic" name="step 0-image-pull-secrets" timestamp="2024-03-14T10:27:42.853144374+01:00" time="1.410" assertions="0"></testcase>
       <testcase classname="central-basic" name="step 10-central-cr" timestamp="2024-03-14T10:27:44.262843517+01:00" time="960.886" assertions="9"></testcase>
       <testcase classname="central-basic" name="step 11-" timestamp="2024-03-14T10:43:45.149194831+01:00" time="1.210" assertions="3"></testcase>
       <testcase classname="central-basic" name="step 20-verify-password" timestamp="2024-03-14T10:43:46.358720862+01:00" time="3.586" assertions="0"></testcase>
       <testcase classname="central-basic" name="step 30-change-password" timestamp="2024-03-14T10:43:49.944607399+01:00" time="0.663" assertions="0"></testcase>
       <testcase classname="central-basic" name="step 40-reconcile" timestamp="2024-03-14T10:43:50.607656485+01:00" time="84.499" assertions="2"></testcase>
       <testcase classname="central-basic" name="step 60-use-new-password" timestamp="2024-03-14T10:45:15.106773843+01:00" time="2.017" assertions="0"></testcase>
       <testcase classname="central-basic" name="step 75-switch-to-external-central-db" timestamp="2024-03-14T10:45:17.124277157+01:00" time="31.584" assertions="3"></testcase>
       <testcase classname="central-basic" name="step 76-switch-back-to-internal-central-db" timestamp="2024-03-14T10:45:48.707986107+01:00" time="375.834" assertions="8">
         <failure message="failed in step 76-switch-back-to-internal-central-db" type="">Get &#34;https://34.123.156.233/api/v1/namespaces/kuttl-test-immense-pipefish/pods?labelSelector=app%3Dcentral&#34;: dial tcp 34.123.156.233:443: i/o timeout</failure>
       </testcase>
     </testsuite>
     <testsuite tests="15" failures="0" timestamp="2024-03-14T10:27:42.499383151+01:00" time="582.342" name="central-misc">
       <testcase classname="central-misc" name="setup" timestamp="2024-03-14T10:27:42.499383924+01:00" time="0.334" assertions="0"></testcase>
       <testcase classname="central-misc" name="step 0-image-pull-secrets" timestamp="2024-03-14T10:27:42.833146338+01:00" time="1.421" assertions="0"></testcase>
       <testcase classname="central-misc" name="step 10-central-cr" timestamp="2024-03-14T10:27:44.254461703+01:00" time="274.741" assertions="9"></testcase>
       <testcase classname="central-misc" name="step 11-" timestamp="2024-03-14T10:32:18.99536279+01:00" time="0.001" assertions="0"></testcase>
       <testcase classname="central-misc" name="step 40-enable-declarative-config" timestamp="2024-03-14T10:32:18.996512371+01:00" time="52.885" assertions="7"></testcase>
       <testcase classname="central-misc" name="step 41-disable-declarative-config" timestamp="2024-03-14T10:33:11.881202981+01:00" time="24.417" assertions="7"></testcase>
       <testcase classname="central-misc" name="step 61-" timestamp="2024-03-14T10:33:36.298495291+01:00" time="27.786" assertions="6"></testcase>
       <testcase classname="central-misc" name="step 62-" timestamp="2024-03-14T10:34:04.084013669+01:00" time="0.001" assertions="0"></testcase>
       <testcase classname="central-misc" name="step 63-" timestamp="2024-03-14T10:34:04.084635668+01:00" time="3.991" assertions="10"></testcase>
       <testcase classname="central-misc" name="step 64-" timestamp="2024-03-14T10:34:08.075894938+01:00" time="0.001" assertions="0"></testcase>
       <testcase classname="central-misc" name="step 80-enable-telemetry" timestamp="2024-03-14T10:34:08.076476289+01:00" time="54.910" assertions="7"></testcase>
       <testcase classname="central-misc" name="step 81-disable-telemetry" timestamp="2024-03-14T10:35:02.986151412+01:00" time="61.031" assertions="7"></testcase>
       <testcase classname="central-misc" name="step 85-add-additional-ca" timestamp="2024-03-14T10:36:04.017433688+01:00" time="29.733" assertions="7"></testcase>
       <testcase classname="central-misc" name="step 900-delete-cr" timestamp="2024-03-14T10:36:33.750642603+01:00" time="47.214" assertions="72"></testcase>
       <testcase classname="central-misc" name="step 990-" timestamp="2024-03-14T10:37:20.964293466+01:00" time="3.878" assertions="10"></testcase>
     </testsuite>
   </testsuite>
   <testsuite tests="3" failures="1" timestamp="2024-03-14T10:27:42.483234892+01:00" time="19.295" name="./tests/controller">
     <testsuite tests="3" failures="1" timestamp="2024-03-14T10:27:42.48581535+01:00" time="19.292" name="metrics">
       <testcase classname="metrics" name="setup" timestamp="2024-03-14T10:27:42.485815837+01:00" time="0.367" assertions="0"></testcase>
       <testcase classname="metrics" name="step 100-rbac" timestamp="2024-03-14T10:27:42.853171423+01:00" time="2.741" assertions="0"></testcase>
       <testcase classname="metrics" name="step 200-access-no-auth" timestamp="2024-03-14T10:27:45.594328284+01:00" time="16.184" assertions="4">
         <failure message="failed in step 200-access-no-auth" type="">resource Pod:kuttl-test-intimate-monitor/operator-metrics-unprivileged: .status.phase: value mismatch, expected: Succeededx != actual: Succeeded</failure>
       </testcase>
     </testsuite>
   </testsuite>
   <testsuite tests="10" failures="1" timestamp="2024-03-14T10:27:42.483247762+01:00" time="1357.557" name="./tests/securedcluster">
     <testsuite tests="10" failures="1" timestamp="2024-03-14T10:27:42.496676933+01:00" time="1357.543" name="sc-basic">
       <testcase classname="sc-basic" name="setup" timestamp="2024-03-14T10:27:42.496677598+01:00" time="0.362" assertions="0"></testcase>
       <testcase classname="sc-basic" name="step 0-image-pull-secrets" timestamp="2024-03-14T10:27:42.858641218+01:00" time="1.405" assertions="0"></testcase>
       <testcase classname="sc-basic" name="step 5-central-cr" timestamp="2024-03-14T10:27:44.263432174+01:00" time="1059.093" assertions="6"></testcase>
       <testcase classname="sc-basic" name="step 7-fetch-bundle" timestamp="2024-03-14T10:45:23.356019926+01:00" time="5.870" assertions="3"></testcase>
       <testcase classname="sc-basic" name="step 10-secured-cluster-cr" timestamp="2024-03-14T10:45:29.226313899+01:00" time="55.764" assertions="5"></testcase>
       <testcase classname="sc-basic" name="step 12-" timestamp="2024-03-14T10:46:24.990194295+01:00" time="2.350" assertions="6"></testcase>
       <testcase classname="sc-basic" name="step 13-add-stackrox-secret" timestamp="2024-03-14T10:46:27.340006671+01:00" time="95.431" assertions="6"></testcase>
       <testcase classname="sc-basic" name="step 14-add-collector-secret" timestamp="2024-03-14T10:48:02.771277222+01:00" time="51.402" assertions="6"></testcase>
       <testcase classname="sc-basic" name="step 15-add-remaining-secrets" timestamp="2024-03-14T10:48:54.173424571+01:00" time="53.147" assertions="6"></testcase>
       <testcase classname="sc-basic" name="step 16-remove-dummy-secrets" timestamp="2024-03-14T10:49:47.320052808+01:00" time="32.720" assertions="6">
         <failure message="failed in step 16-remove-dummy-secrets" type="">retrieving API resource for /v1, Kind=Secret failed: Get &#34;https://34.123.156.233/api/v1?timeout=32s&#34;: net/http: request canceled (Client.Timeout exceeded while awaiting headers)</failure>
       </testcase>
     </testsuite>
   </testsuite>
 </testsuites>