Index: tests/test.py
===================================================================
--- tests/test.py	(revision 8ecb5905164f38056d37409e6df651664e57e783)
+++ tests/test.py	(revision e791851b1b0c5ac5ca5e16308a9ab2d480284d29)
@@ -202,13 +202,8 @@
 		if error :
 			text = text + '\n' + error
-			out = sys.stderr
-
-		print(text, file = out)
-		sys.stdout.flush()
-		sys.stderr.flush()
-
-		return retcode != TestResult.SUCCESS
+
+		return retcode == TestResult.SUCCESS, text
 	except KeyboardInterrupt:
-		False
+		False, ""
 
 # run the given list of tests with the given parameters
@@ -220,24 +215,37 @@
 	pool = multiprocessing.Pool(jobs)
 
+	failed = False
+
 	# for each test to run
 	try :
-		results = pool.map_async(
+		num = len(tests)
+		fancy = sys.stdout.isatty()
+		for i, (succ, txt) in enumerate(pool.imap(
 			run_test_worker,
 			tests,
 			chunksize = 1
-		).get(settings.timeout.total)
+		)) :
+			if not succ :
+				failed = True
+
+			print("       " + txt)
+
+			if(fancy and i != num):
+				print("%d/%d" % (i, num), end='\r')
+				sys.stdout.flush()
+
 	except KeyboardInterrupt:
 		pool.terminate()
-		print("Tests interrupted by user")
-		sys.exit(1)
+		print("Tests interrupted by user", file=sys.stderr)
+		failed = True
+	except multiprocessing.TimeoutError:
+		pool.terminate()
+		print("ERROR: Test suite timed out", file=sys.stderr)
+		failed = True
 
 	# clean the workspace
 	make('clean', output=subprocess.DEVNULL, error=subprocess.DEVNULL)
 
-	for failed in results:
-		if failed :
-			return 1
-
-	return 0
+	return 1 if failed else 0
 
 
