diff --git a/.travis.yml b/.travis.yml
index 1e59294f3f2ef3b92a985033f9cfc2b94cade626..d102f3d84777f0faccfebfcd2100bf568c51ae51 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,4 @@
 language: cpp
-script: ./tools/run_tests/run_tests.py -lc
+script: ./tools/run_tests/run_tests.py -lc -t -j2
 notifications:
   email: false
diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py
index 569cb5bac2090719d6e0cff3d0b57d0fe935ed48..575d2c5902d4a90dfae9c6f0c6509eb4dc97ad4a 100755
--- a/tools/run_tests/jobset.py
+++ b/tools/run_tests/jobset.py
@@ -154,7 +154,7 @@ class JobSpec(object):
 class Job(object):
   """Manages one job."""
 
-  def __init__(self, spec, bin_hash, newline_on_success):
+  def __init__(self, spec, bin_hash, newline_on_success, travis):
     self._spec = spec
     self._bin_hash = bin_hash
     self._tempfile = tempfile.TemporaryFile()
@@ -167,7 +167,9 @@ class Job(object):
                                      env=env)
     self._state = _RUNNING
     self._newline_on_success = newline_on_success
-    message('START', spec.shortname)
+    self._travis = travis
+    if not travis:
+      message('START', spec.shortname)
 
   def state(self, update_cache):
     """Poll current state of the job. Prints messages at completion."""
@@ -181,7 +183,7 @@ class Job(object):
       else:
         self._state = _SUCCESS
         message('PASSED', self._spec.shortname,
-                do_newline=self._newline_on_success)
+                do_newline=self._newline_on_success or self._travis)
         if self._bin_hash:
           update_cache.finished(self._spec.identity(), self._bin_hash)
     return self._state
@@ -195,7 +197,7 @@ class Job(object):
 class Jobset(object):
   """Manages one run of jobs."""
 
-  def __init__(self, check_cancelled, maxjobs, newline_on_success, cache):
+  def __init__(self, check_cancelled, maxjobs, newline_on_success, travis, cache):
     self._running = set()
     self._check_cancelled = check_cancelled
     self._cancelled = False
@@ -203,6 +205,7 @@ class Jobset(object):
     self._completed = 0
     self._maxjobs = maxjobs
     self._newline_on_success = newline_on_success
+    self._travis = travis
     self._cache = cache
 
   def start(self, spec):
@@ -224,7 +227,8 @@ class Jobset(object):
     if should_run:
       self._running.add(Job(spec,
                             bin_hash,
-                            self._newline_on_success))
+                            self._newline_on_success,
+                            self._travis))
     return True
 
   def reap(self):
@@ -240,8 +244,9 @@ class Jobset(object):
         self._completed += 1
         self._running.remove(job)
       if dead: return
-      message('WAITING', '%d jobs running, %d complete, %d failed' % (
-          len(self._running), self._completed, self._failures))
+      if (not self._travis):
+        message('WAITING', '%d jobs running, %d complete, %d failed' % (
+            len(self._running), self._completed, self._failures))
       signal.pause()
 
   def cancelled(self):
@@ -277,10 +282,11 @@ def run(cmdlines,
         check_cancelled=_never_cancelled,
         maxjobs=None,
         newline_on_success=False,
+        travis=False,
         cache=None):
   js = Jobset(check_cancelled,
               maxjobs if maxjobs is not None else _DEFAULT_MAX_JOBS,
-              newline_on_success,
+              newline_on_success, travis,
               cache if cache is not None else NoCache())
   for cmdline in shuffle_iteratable(cmdlines):
     if not js.start(cmdline):
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 7c6a050a675e6d46c5d74c345045fc9e2b0a8e35..5942ae91801a4d67580b99f5ec18ee6fd3a63368 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -175,6 +175,10 @@ argp.add_argument('-f', '--forever',
                   default=False,
                   action='store_const',
                   const=True)
+argp.add_argument('-t', '--travis',
+                  default=False,
+                  action='store_const',
+                  const=True)
 argp.add_argument('--newline_on_success',
                   default=False,
                   action='store_const',
@@ -251,17 +255,18 @@ class TestCache(object):
         self.parse(json.loads(f.read()))
 
 
-def _build_and_run(check_cancelled, newline_on_success, cache):
+def _build_and_run(check_cancelled, newline_on_success, travis, cache):
   """Do one pass of building & running tests."""
   # build latest sequentially
-  if not jobset.run(build_steps, maxjobs=1):
+  if not jobset.run(build_steps, maxjobs=1,
+                    newline_on_success=newline_on_success, travis=travis):
     return 1
 
   # run all the tests
   all_runs = itertools.chain.from_iterable(
       itertools.repeat(one_run, runs_per_test))
   if not jobset.run(all_runs, check_cancelled,
-                    newline_on_success=newline_on_success,
+                    newline_on_success=newline_on_success, travis=travis,
                     maxjobs=min(args.jobs, min(c.maxjobs for c in run_configs)),
                     cache=cache):
     return 2
@@ -292,6 +297,7 @@ if forever:
 else:
   result = _build_and_run(check_cancelled=lambda: False,
                           newline_on_success=args.newline_on_success,
+                          travis=args.travis,
                           cache=test_cache)
   if result == 0:
     jobset.message('SUCCESS', 'All tests passed', do_newline=True)