Index: src/Common/SemanticError.cc
===================================================================
--- src/Common/SemanticError.cc	(revision cdb990a3f4e49d6faf7cbdf00fb2350033fd78cb)
+++ src/Common/SemanticError.cc	(revision ccdab45b3315fda7612567b5ba04ded87e412b8e)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed May  2 18:13:37 2018
-// Update Count     : 8
+// Last Modified On : Wed May 16 15:01:20 2018
+// Update Count     : 9
 //
 
@@ -70,4 +70,6 @@
 //-----------------------------------------------------------------------------
 // Semantic Error
+bool SemanticErrorThrow = false;
+
 SemanticErrorException::SemanticErrorException( CodeLocation location, std::string error ) {
 	append( location, error );
@@ -94,4 +96,5 @@
 
 void SemanticError( CodeLocation location, std::string error ) {
+	SemanticErrorThrow = true;
 	throw SemanticErrorException(location, error);
 }
Index: src/Common/SemanticError.h
===================================================================
--- src/Common/SemanticError.h	(revision cdb990a3f4e49d6faf7cbdf00fb2350033fd78cb)
+++ src/Common/SemanticError.h	(revision ccdab45b3315fda7612567b5ba04ded87e412b8e)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed May  2 18:13:15 2018
-// Update Count     : 29
+// Last Modified On : Wed May 16 15:01:23 2018
+// Update Count     : 30
 //
 
@@ -21,4 +21,6 @@
 //-----------------------------------------------------------------------------
 // Errors
+
+extern bool SemanticErrorThrow;
 
 __attribute__((noreturn)) void SemanticError( CodeLocation location, std::string error );
Index: src/tests/pybin/test_run.py
===================================================================
--- src/tests/pybin/test_run.py	(revision cdb990a3f4e49d6faf7cbdf00fb2350033fd78cb)
+++ src/tests/pybin/test_run.py	(revision ccdab45b3315fda7612567b5ba04ded87e412b8e)
@@ -4,4 +4,16 @@
 
 import pybin.settings
+import datetime
+
+from string import Template
+
+class DeltaTemplate(Template):
+    delimiter = "%"
+
+def strfdelta(tdelta, fmt):
+    d["H"], rem = divmod(tdelta.seconds, 3600)
+    d["M"], d["S"] = divmod(rem, 60)
+    t = DeltaTemplate(fmt)
+    return t.substitute(**d)
 
 # Test class that defines what a test is
@@ -57,11 +69,23 @@
 
 	@classmethod
-	def toString( cls, retcode ):
+	def toString( cls, retcode, duration ):
 		if settings.generating :
-			if   retcode == TestResult.SUCCESS: 	return "Done"
-			elif retcode == TestResult.TIMEOUT: 	return "TIMEOUT"
-			else :						return "ERROR code %d" % retcode
+			if   retcode == TestResult.SUCCESS: 	text = "Done   "
+			elif retcode == TestResult.TIMEOUT: 	text = "TIMEOUT"
+			else :						text = "ERROR code %d" % retcode
 		else :
-			if   retcode == TestResult.SUCCESS: 	return "PASSED"
-			elif retcode == TestResult.TIMEOUT: 	return "TIMEOUT"
-			else :						return "FAILED with code %d" % retcode
+			if   retcode == TestResult.SUCCESS: 	text = "PASSED "
+			elif retcode == TestResult.TIMEOUT: 	text = "TIMEOUT"
+			else :						text = "FAILED with code %d" % retcode
+
+		text += "    C%s - R%s" % (cls.fmtDur(duration[0]), cls.fmtDur(duration[1]))
+		return text
+
+	@classmethod
+	def fmtDur( cls, duration ):
+		if duration :
+			hours, rem = divmod(duration, 3600)
+			minutes, rem = divmod(rem, 60)
+			seconds, millis = divmod(rem, 1)
+			return "%2d:%02d.%03d" % (minutes, seconds, millis * 1000)
+		return " n/a"
Index: src/tests/pybin/tools.py
===================================================================
--- src/tests/pybin/tools.py	(revision cdb990a3f4e49d6faf7cbdf00fb2350033fd78cb)
+++ src/tests/pybin/tools.py	(revision ccdab45b3315fda7612567b5ba04ded87e412b8e)
@@ -168,12 +168,16 @@
 def jobCount( options, tests ):
 	# check if the user already passed in a number of jobs for multi-threading
-	make_flags = os.environ.get('MAKEFLAGS')
-	make_jobs_fds = re.search("--jobserver-(auth|fds)=\s*([0-9]+),([0-9]+)", make_flags) if make_flags else None
-	if make_jobs_fds :
-		tokens = os.read(int(make_jobs_fds.group(2)), 1024)
-		options.jobs = len(tokens)
-		os.write(int(make_jobs_fds.group(3)), tokens)
+	if not options.jobs:
+		make_flags = os.environ.get('MAKEFLAGS')
+		force = bool(make_flags)
+		make_jobs_fds = re.search("--jobserver-(auth|fds)=\s*([0-9]+),([0-9]+)", make_flags) if make_flags else None
+		if make_jobs_fds :
+			tokens = os.read(int(make_jobs_fds.group(2)), 1024)
+			options.jobs = len(tokens)
+			os.write(int(make_jobs_fds.group(3)), tokens)
+		else :
+			options.jobs = multiprocessing.cpu_count()
 	else :
-		options.jobs = multiprocessing.cpu_count()
+		force = True
 
 	# make sure we have a valid number of jobs that corresponds to user input
@@ -182,5 +186,5 @@
 		sys.exit(1)
 
-	return min( options.jobs, len(tests) ), True if make_flags else False
+	return min( options.jobs, len(tests) ), force
 
 # setup a proper processor pool with correct signal handling
Index: src/tests/test.py
===================================================================
--- src/tests/test.py	(revision cdb990a3f4e49d6faf7cbdf00fb2350033fd78cb)
+++ src/tests/test.py	(revision ccdab45b3315fda7612567b5ba04ded87e412b8e)
@@ -9,4 +9,5 @@
 import re
 import sys
+import time
 
 ################################################################################
@@ -95,5 +96,5 @@
 	parser.add_argument('--all', help='Run all test available', action='store_true')
 	parser.add_argument('--regenerate-expected', help='Regenerate the .expect by running the specified tets, can be used with --all option', action='store_true')
-	parser.add_argument('-j', '--jobs', help='Number of tests to run simultaneously', type=int, default='8')
+	parser.add_argument('-j', '--jobs', help='Number of tests to run simultaneously', type=int)
 	parser.add_argument('--list-comp', help='List all valide arguments', action='store_true')
 	parser.add_argument('-I','--include', help='Directory of test to include, can be used multiple time, All  if omitted', action='append')
@@ -136,11 +137,18 @@
 
 	# build, skipping to next test on error
+	before = time.time()
 	make_ret, _ = make( test.target(),
 		redirects  = "2> %s 1> /dev/null" % out_file,
 		error_file = err_file
 	)
+	after = time.time()
+
+	comp_dur = after - before
+
+	run_dur = None
 
 	# if the make command succeds continue otherwise skip to diff
 	if make_ret == 0 or settings.dry_run:
+		before = time.time()
 		if settings.dry_run or fileIsExecutable(test.target()) :
 			# run test
@@ -149,4 +157,7 @@
 			# simply cat the result into the output
 			retcode, _ = sh("cat %s > %s" % (test.target(), out_file))
+
+		after = time.time()
+		run_dur = after - before
 	else:
 		retcode, _ = sh("mv %s %s" % (err_file, out_file))
@@ -174,5 +185,5 @@
 	sh("rm -f %s > /dev/null 2>&1" % test.target())
 
-	return retcode, error
+	return retcode, error, [comp_dur, run_dur]
 
 # run a single test and handle the errors, outputs, printing, exception handling, etc.
@@ -183,8 +194,8 @@
 		name_txt = "%20s  " % t.name
 
-		retcode, error = run_single_test(t)
+		retcode, error, duration = run_single_test(t)
 
 		# update output based on current action
-		result_txt = TestResult.toString( retcode )
+		result_txt = TestResult.toString( retcode, duration )
 
 		#print result with error if needed
