Add '--slowest' option to 'tempest run'

A common pattern in some projects running tests with stestr is to
output the slowest tests from the test run after it finishes by running
'stestr slowest' after 'stestr run'.

We can do something similar in 'tempest run' with a '--slowest' option
that will run 'stestr slowest' when passed.

This addition is inspired by seeing TIMED_OUT job failures in the gate
with tests run using 'tempest run'. We could consider adding the
'--slowest' option to those command lines to make it easier to identify
the slowest tests in the job logs and potentially work on improving
their runtimes.

Change-Id: Ia88dabcb41d56d4246337ba67c140a93342ad6ab
diff --git a/tempest/cmd/run.py b/tempest/cmd/run.py
index 2669ff7..e305646 100644
--- a/tempest/cmd/run.py
+++ b/tempest/cmd/run.py
@@ -269,6 +269,8 @@
                 return_code = commands.run_command(
                     **params, blacklist_file=ex_list,
                     whitelist_file=in_list, black_regex=ex_regex)
+            if parsed_args.slowest:
+                commands.slowest_command()
             if return_code > 0:
                 sys.exit(return_code)
         return return_code
@@ -392,6 +394,9 @@
                             help='Combine the output of this run with the '
                                  "previous run's as a combined stream in the "
                                  "stestr repository after it finish")
+        parser.add_argument('--slowest', action='store_true',
+                            help='Show the longest running tests in the '
+                                 'stestr repository after it finishes')
 
         parser.set_defaults(parallel=True)
         return parser
diff --git a/tempest/tests/cmd/test_run.py b/tempest/tests/cmd/test_run.py
index 3b5e901..b487c3f 100644
--- a/tempest/tests/cmd/test_run.py
+++ b/tempest/tests/cmd/test_run.py
@@ -225,6 +225,11 @@
                             '%s=%s' % (self.exclude_list, path),
                             '--regex', 'fail'], 1)
 
+    def test_tempest_run_with_slowest(self):
+        out, err = self.assertRunExit(['tempest', 'run', '--regex', 'passing',
+                                       '--slowest'], 0)
+        self.assertRegex(str(out), r'Test id\s+Runtime \(s\)')
+
 
 class TestOldArgRunReturnCode(TestRunReturnCode):
     """A class for testing deprecated but still supported args.
@@ -363,6 +368,7 @@
         parsed_args.state = None
         parsed_args.list_tests = False
         parsed_args.config_file = path
+        parsed_args.slowest = False
 
         with mock.patch('stestr.commands.run_command') as m:
             m.return_value = 0
@@ -393,6 +399,7 @@
         parsed_args.state = None
         parsed_args.list_tests = False
         parsed_args.config_file = path
+        parsed_args.slowest = False
 
         with mock.patch('stestr.commands.run_command') as m:
             m.return_value = 0
@@ -409,6 +416,7 @@
         parsed_args.state = None
         parsed_args.list_tests = False
         parsed_args.config_file = ''
+        parsed_args.slowest = False
 
         with mock.patch('stestr.commands.run_command') as m:
             m.return_value = 0
@@ -441,6 +449,7 @@
         parsed_args.state = True
         parsed_args.list_tests = False
         parsed_args.config_file = ''
+        parsed_args.slowest = False
 
         with mock.patch('stestr.commands.run_command') as m:
             m.return_value = 0
@@ -460,6 +469,7 @@
         parsed_args.state = True
         parsed_args.list_tests = False
         parsed_args.config_file = path
+        parsed_args.slowest = False
 
         with mock.patch('stestr.commands.run_command') as m:
             m.return_value = 0