diff --git a/.codecov.yml b/.codecov.yml
index 11af0577da85238b68638bbda335f9c1c81289b0..93ce22ee7f27853145f03c0f40d98f3cb5a2c006 100644
--- a/.codecov.yml
+++ b/.codecov.yml
@@ -29,7 +29,6 @@ coverage:
 
 ignore:
   - lib/spack/spack/test/.*
-  - lib/spack/env/.*
   - lib/spack/docs/.*
   - lib/spack/external/.*
 
diff --git a/.coveragerc b/.coveragerc
index 0201a4b502d9238026305a1982a8f4a75d8df977..c0c5f76688b5b5f51c1372e10bdb48967a815070 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -7,7 +7,6 @@ branch = True
 source = lib
 omit =
      lib/spack/spack/test/*
-     lib/spack/env/*
      lib/spack/docs/*
      lib/spack/external/*
 
diff --git a/.travis.yml b/.travis.yml
index 5e74b7dd93e14c05258aa2f50d9aa2a0ea53a6ee..481372adf88957d852aa70456431c0ae9ea9ef46 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -133,17 +133,19 @@ addons:
   apt:
     packages:
       - ccache
+      - cmake
       - gfortran
-      - mercurial
       - graphviz
       - gnupg2
-      - cmake
+      - kcov
+      - mercurial
       - ninja-build
+      - perl
+      - perl-base
+      - realpath
       - r-base
       - r-base-core
       - r-base-dev
-      - perl
-      - perl-base
   # for Mac builds, we use Homebrew
   homebrew:
     packages:
diff --git a/share/spack/qa/bashcov b/share/spack/qa/bashcov
new file mode 100755
index 0000000000000000000000000000000000000000..58fa4fe0d05939fea07e992144bb267968a63fc0
--- /dev/null
+++ b/share/spack/qa/bashcov
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# This script acts like bash but runs kcov on the input script. We use it
+# to get coverage for Spack's bash scripts.
+#
+
+if [ -z "$SPACK_ROOT" ]; then
+    echo "ERROR: SPACK_ROOT was not set!"
+    exit 1
+fi
+
+kcov "$SPACK_ROOT/coverage" "$@"
diff --git a/share/spack/qa/setup.sh b/share/spack/qa/setup.sh
index 4f40904433466c50483868f9cfce358915874fef..4592c7ea85f1a14758a0aef989a83db570219fe8 100755
--- a/share/spack/qa/setup.sh
+++ b/share/spack/qa/setup.sh
@@ -11,15 +11,28 @@
 #
 
 QA_DIR="$(dirname ${BASH_SOURCE[0]})"
-SPACK_ROOT="$QA_DIR/../../.."
+export SPACK_ROOT=$(realpath "$QA_DIR/../../..")
 
 # Source the setup script
 . "$SPACK_ROOT/share/spack/setup-env.sh"
 
 # Set up some variables for running coverage tests.
 if [[ "$TEST_SUITE" == "unit" || "$TEST_SUITE" == "build" ]]; then
+    # these set up coverage for Python
     coverage=coverage
     coverage_run="coverage run"
+
+    # make a coverage directory for kcov, and patch cc to use our bashcov
+    # script instead of plain bash
+    if [[ $TEST_SUITE == unit &&   # kcov segfaults for the MPICH build test
+          $TRAVIS_OS_NAME == linux &&
+          $TRAVIS_PYTHON_VERSION != 2.6 ]];
+    then
+        mkdir -p coverage
+        cc_script="$SPACK_ROOT/lib/spack/env/cc"
+        bashcov=$(realpath ${QA_DIR}/bashcov)
+        sed -i~ "s@#\!/bin/bash@#\!${bashcov}@" "$cc_script"
+    fi
 else
     coverage=""
     coverage_run=""