Skip to content

Karma with Jenkins

Jenkins remains extremely common in enterprises with existing Angular/Karma test suites. This lesson covers a working Jenkinsfile pipeline, including JUnit result publishing — a feature Jenkins supports natively and thoroughly.

A Complete Jenkinsfile Example

Jenkins' declarative pipeline syntax maps closely onto the same steps used elsewhere: install dependencies, run tests headlessly, then publish generated results using Jenkins' built-in JUnit and HTML publisher plugins.

// Jenkinsfile
pipeline {
  agent any

  stages {
    stage('Install') {
      steps {
        sh 'npm ci'
      }
    }

    stage('Test') {
      steps {
        sh 'npx karma start --single-run --browsers ChromeHeadlessCI'
      }
    }
  }

  post {
    always {
      junit 'test-results/*.xml'
      archiveArtifacts artifacts: 'coverage/**', allowEmptyArchive: true
    }
  }
}

Jenkins' built-in junit pipeline step natively understands the JUnit XML karma-junit-reporter generates — no extra plugin configuration is required beyond pointing it at the file glob.

Ensuring Chrome Is Available on Jenkins Agents

# Option 1: install Chrome/Chromium directly on the Jenkins agent
apt-get install -y chromium-browser

# Option 2: use a Docker-based agent with Chrome preinstalled
agent {
  docker { image 'node:20-bookworm' }
}
# (then install/verify Chrome inside that image, or use an image that bundles it)
  • Jenkins agents vary widely in what's preinstalled — verify Chrome/Chromium availability explicitly rather than assuming it.
  • Docker-based agents give more consistent, reproducible environments across different Jenkins setups.
  • CHROME_BIN may need to be set explicitly depending on how the agent's Chrome/Chromium was installed.
  • The junit pipeline step is a Jenkins core feature, requiring no additional plugin installation in most modern Jenkins versions.

Jenkins + Karma Cheat Sheet

Key pipeline steps and what they handle.

Step Purpose
sh 'npm ci' Installs exact locked dependency versions
sh 'npx karma start --single-run ...' Runs the headless test suite
junit 'test-results/*.xml' Publishes JUnit results natively in Jenkins' UI
archiveArtifacts Archives coverage reports or other generated files
post { always { ... } } Runs cleanup/reporting steps regardless of test outcome

Making Jenkins Fail the Build Correctly

Because karma start --single-run exits with a non-zero code on any test failure, Jenkins' sh step automatically fails the pipeline stage — no extra logic is needed to propagate the failure, as long as you don't accidentally swallow the exit code.

// Avoid this — it can swallow the real exit code depending on shell settings:
sh 'npx karma start --single-run || true'

// Prefer this — let a genuine failure fail the build:
sh 'npx karma start --single-run --browsers ChromeHeadlessCI'

|| true is sometimes added temporarily while debugging a flaky pipeline, but should never remain in a real pipeline definition.

Enforcing Coverage Thresholds via Jenkins

If coverageReporter.check (covered earlier) is configured with meaningful thresholds, Jenkins needs no extra plugin logic — a threshold breach already causes Karma itself to exit non-zero, which Jenkins reports as a failed build automatically.

Common Mistakes

  • Adding || true (or similar) to the test step, silently hiding real test failures from Jenkins.
  • Assuming every Jenkins agent has Chrome preinstalled without verifying it explicitly.
  • Forgetting the post { always { ... } } block, losing JUnit/coverage publishing on failed builds specifically.
  • Not setting CHROME_BIN when the agent's Chrome install lives somewhere the launcher doesn't check automatically.

Key Takeaways

  • Jenkins' declarative pipeline syntax maps directly onto install, test, and publish stages.
  • The built-in junit step natively understands karma-junit-reporter's generated XML output.
  • Never swallow a test step's exit code with || true in a real pipeline definition.
  • Coverage thresholds fail the Jenkins build automatically through Karma's own non-zero exit code.

Pro Tip

Use post { always { ... } } for anything you want published regardless of pass/fail — JUnit results, coverage reports, and logs are almost always more valuable on a failed build than a passing one, so make sure they're never skipped.