Hello community, here is the log from the commit of package python-os-testr for openSUSE:Factory checked in at 2016-11-15 18:01:33 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-os-testr (Old) and /work/SRC/openSUSE:Factory/.python-os-testr.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-os-testr" Changes: -------- --- /work/SRC/openSUSE:Factory/python-os-testr/python-os-testr.changes 2016-09-01 14:02:46.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-os-testr.new/python-os-testr.changes 2016-11-15 18:01:34.000000000 +0100 @@ -1,0 +2,25 @@ +Mon Nov 14 18:18:45 UTC 2016 - [email protected] + +update to version 0.8.0 + * Remove discover from test-requirements + * Remove the TODO file + * Delete openstack/common in flake8 exclude list + * Make subprocess outputs to text for Python 3 + * Handle overlapping black regexes + * Sort failed tests at the top on HTML result page + * Update home-page url + * Add --black-regex/-B option + * Add ostestr as a function + * Use dash instead of underscore in args + * Simplify logic in _get_test_list + * Fix doc warnings and disable smarty-pants + * Add documentation for generate-subunit + * Construct a list of test cases instead of passing a regexp + * Allow to specifiy black/white list at the same time + * Make unexpected success as fail + * Make the listbuilder the default strategy + * Error on invalid list parameter combination + * Updated from global requirements + * Add support for Python versions + +------------------------------------------------------------------- Old: ---- os-testr-0.7.0.tar.gz New: ---- os-testr-0.8.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-os-testr.spec ++++++ --- /var/tmp/diff_new_pack.H9vifB/_old 2016-11-15 18:01:35.000000000 +0100 +++ /var/tmp/diff_new_pack.H9vifB/_new 2016-11-15 18:01:35.000000000 +0100 @@ -18,13 +18,13 @@ %global sname os-testr Name: python-os-testr -Version: 0.7.0 +Version: 0.8.0 Release: 0 Summary: A testr wrapper to provide functionality for OpenStack projects License: Apache-2.0 Group: Development/Languages/Python -Url: http://www.openstack.org/ -Source: https://pypi.io/packages/source/o/%{sname}/%{sname}-%{version}.tar.gz +Url: http://docs.openstack.org/developer/os-testr +Source0: https://pypi.io/packages/source/o/%{sname}/%{sname}-%{version}.tar.gz BuildRequires: openstack-macros BuildRequires: python-ddt >= 1.0.1 BuildRequires: python-devel @@ -58,7 +58,7 @@ %setup -q -n %{sname}-%{version} %build -%{__python2} setup.py build +%{py2_build} # generate html docs %{__python2} setup.py build_sphinx @@ -66,7 +66,7 @@ rm -rf doc/build/html/.{doctrees,buildinfo} %install -%{__python2} setup.py install --prefix=%{_prefix} --root=%{buildroot} +%{py2_install} %check export PATH="$PATH:%{buildroot}/%{_bindir}" ++++++ _service ++++++ --- /var/tmp/diff_new_pack.H9vifB/_old 2016-11-15 18:01:35.000000000 +0100 +++ /var/tmp/diff_new_pack.H9vifB/_new 2016-11-15 18:01:35.000000000 +0100 @@ -1,8 +1,8 @@ <services> <service mode="disabled" name="renderspec"> - <param name="input-template">https://raw.githubusercontent.com/openstack/rpm-packaging/master/openstack/os-testr/os-testr.spec.j2</param> + <param name="input-template">https://raw.githubusercontent.com/openstack/rpm-packaging/stable/newton/openstack/os-testr/os-testr.spec.j2</param> <param name="output-name">python-os-testr.spec</param> - <param name="requirements">https://raw.githubusercontent.com/openstack/rpm-packaging/master/global-requirements.txt</param> + <param name="requirements">https://raw.githubusercontent.com/openstack/rpm-packaging/stable/newton/global-requirements.txt</param> </service> <service mode="disabled" name="download_files"> <param name="changesgenerate">enable</param> @@ -10,4 +10,5 @@ <service name="refresh_patches" mode="disabled"> <param name="changesgenerate">enable</param> </service> + <service name="format_spec_file" mode="disabled"/> </services> ++++++ os-testr-0.7.0.tar.gz -> os-testr-0.8.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/AUTHORS new/os-testr-0.8.0/AUTHORS --- old/os-testr-0.7.0/AUTHORS 2016-05-26 21:45:23.000000000 +0200 +++ new/os-testr-0.8.0/AUTHORS 2016-09-28 21:26:08.000000000 +0200 @@ -1,4 +1,5 @@ Assaf Muller <[email protected]> +Attila Fazekas <[email protected]> Christian Berendt <[email protected]> Davanum Srinivas <[email protected]> Doug Hellmann <[email protected]> @@ -14,5 +15,7 @@ TerryHowe <[email protected]> Thomas Bechtold <[email protected]> Yushiro FURUKAWA <[email protected]> +guo yunxian <[email protected]> janonymous <[email protected]> +melanie witt <[email protected]> step6829 <[email protected]> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/ChangeLog new/os-testr-0.8.0/ChangeLog --- old/os-testr-0.7.0/ChangeLog 2016-05-26 21:45:23.000000000 +0200 +++ new/os-testr-0.8.0/ChangeLog 2016-09-28 21:26:08.000000000 +0200 @@ -1,6 +1,32 @@ CHANGES ======= +0.8.0 +----- + +* Updated from global requirements +* Handle overlapping black regexes +* Updated from global requirements +* Update home-page url +* Add ostestr as a function +* Error on invalid list parameter combination +* Use dash instead of underscore in args +* Add --black-regex/-B option +* Allow to specifiy black/white list at the same time +* Make the listbuilder the default strategy +* Construct a list of test cases instead of passing a regexp +* Add support for Python versions +* Delete openstack/common in flake8 exclude list +* Simplify logic in _get_test_list +* Remove discover from test-requirements +* Make subprocess outputs to text for Python 3 +* Fix doc warnings and disable smarty-pants +* Updated from global requirements +* Remove the TODO file +* Make unexpected success as fail +* Add documentation for generate-subunit +* Sort failed tests at the top on HTML result page + 0.7.0 ----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/PKG-INFO new/os-testr-0.8.0/PKG-INFO --- old/os-testr-0.7.0/PKG-INFO 2016-05-26 21:45:24.000000000 +0200 +++ new/os-testr-0.8.0/PKG-INFO 2016-09-28 21:26:08.000000000 +0200 @@ -1,8 +1,8 @@ Metadata-Version: 1.1 Name: os-testr -Version: 0.7.0 +Version: 0.8.0 Summary: A testr wrapper to provide functionality for OpenStack projects -Home-page: http://www.openstack.org/ +Home-page: http://docs.openstack.org/developer/os-testr/ Author: OpenStack Author-email: [email protected] License: UNKNOWN @@ -33,6 +33,7 @@ * ``subunit-trace``: an output filter for a subunit stream which provides useful information about the run * ``subunit2html``: generates a test results html page from a subunit stream + * ``generate-subunit``: generate a subunit stream for a single test Platform: UNKNOWN @@ -46,3 +47,4 @@ Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/README.rst new/os-testr-0.8.0/README.rst --- old/os-testr-0.7.0/README.rst 2016-05-26 21:42:56.000000000 +0200 +++ new/os-testr-0.8.0/README.rst 2016-09-28 21:24:04.000000000 +0200 @@ -25,3 +25,4 @@ * ``subunit-trace``: an output filter for a subunit stream which provides useful information about the run * ``subunit2html``: generates a test results html page from a subunit stream +* ``generate-subunit``: generate a subunit stream for a single test diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/TODO.rst new/os-testr-0.8.0/TODO.rst --- old/os-testr-0.7.0/TODO.rst 2016-05-26 21:42:56.000000000 +0200 +++ new/os-testr-0.8.0/TODO.rst 1970-01-01 01:00:00.000000000 +0100 @@ -1,19 +0,0 @@ -Work Items for os-testr -======================= - -Short Term ----------- - * Expose all subunit-trace options through ostestr - * Add --html option to ostestr to run testr with subunit2html output - * Add unit tests - * For ostestr test selection api - * Response code validation on more argument permutations -Long Term ---------- - * Lock down test selection CLI - * When this is done it will become release 1.0.0 - * Add subunit-trace functional tests - ** Sample subunit streams and test output from subunit-trace - * Add testing for subunit2html - * Stop using subprocess in ostestr, everything it uses is python so there - isn't a need to shell out for everything. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/doc/source/conf.py new/os-testr-0.8.0/doc/source/conf.py --- old/os-testr-0.7.0/doc/source/conf.py 2016-05-26 21:42:56.000000000 +0200 +++ new/os-testr-0.8.0/doc/source/conf.py 2016-09-28 21:24:04.000000000 +0200 @@ -58,6 +58,10 @@ # html_theme = '_theme' # html_static_path = ['static'] +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +html_use_smartypants = False + # Output file base name for HTML help builder. htmlhelp_basename = '%sdoc' % project diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/doc/source/generate_subunit.rst new/os-testr-0.8.0/doc/source/generate_subunit.rst --- old/os-testr-0.7.0/doc/source/generate_subunit.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/os-testr-0.8.0/doc/source/generate_subunit.rst 2016-09-28 21:24:04.000000000 +0200 @@ -0,0 +1,51 @@ +.. generate_subunit: + +generate-subunit +================ + +generate-subunit is a simple tool to, as its name implies, generate a subunit +stream. It will generate a stream with a single test result to STDOUT. The +subunit protocol lets you concatenate multiple streams together so if you want +to generate a stream with multiple just append the output of multiple executions +of generate-subunit. + +Summary +------- + + generate-subunit timestamp secs [status] [test_id] + +Usage +----- + +generate-subunit has 2 mandatory arguments. These are needed to specify when +the "test" started running and how long it took. The first argument is a POSIX +timestamp (which can returned by the date util using ``date +%s``) for when it +started running. The second argument is the number of seconds it took for the +execution to finish. For example:: + + $ generate-subunit $(date +%s) 42 + +will generate a stream with the test_id 'devstack' successfully running for 42 +secs starting when the command was executed. This leads into the 2 optional +arguments. The first optional argument is for specifying the status. This must +be the 3rd argument when calling generate-subunit. Valid status options can +be found in the `testtools documentation`_. If status is not specified it will +default to success. For example:: + + $ generate-subunit $(date +%s) 42 fail + +will be the same as the previous example except that it marks the test as +failing. + +.. _testtools documentation: http://testtools.readthedocs.io/en/latest/api.html#testtools.StreamResult.status + +The other optional argument is the test_id (aka test name) and is used to +identify the "test" being run. For better or worse this defaults to *devstack*. +(which is an artifact of why this tool was originally created) Note, this must +be the 4th argument when calling generate-subunit. This means you also must +specify a status if you want to set your own test_id. For example:: + + $ generate-subunit %(date +%s) 42 fail my_little_test + +will generate a subunit stream as before except instead the test will be named +my_little_test. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/doc/source/index.rst new/os-testr-0.8.0/doc/source/index.rst --- old/os-testr-0.7.0/doc/source/index.rst 2016-05-26 21:42:56.000000000 +0200 +++ new/os-testr-0.8.0/doc/source/index.rst 2016-09-28 21:24:04.000000000 +0200 @@ -15,7 +15,6 @@ installation usage contributing - todo history Indices and tables diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/doc/source/ostestr.rst new/os-testr-0.8.0/doc/source/ostestr.rst --- old/os-testr-0.7.0/doc/source/ostestr.rst 2016-05-26 21:42:58.000000000 +0200 +++ new/os-testr-0.8.0/doc/source/ostestr.rst 2016-09-28 21:24:04.000000000 +0200 @@ -13,8 +13,8 @@ Summary ------- - ostestr [-b|--blacklist_file <blacklist_file>] [-r|--regex REGEX] - [-w|--whitelist_file <whitelist_file>] + ostestr [-b|--blacklist-file <blacklist_file>] [-r|--regex REGEX] + [-w|--whitelist-file <whitelist_file>] [-p|--pretty] [--no-pretty] [-s|--subunit] [-l|--list] [-n|--no-discover <test_id>] [--slowest] [--no-slowest] [--pdb <test_id>] [--parallel] [--serial] @@ -23,16 +23,19 @@ Options ------- - --blacklist_file BLACKLIST_FILE, -b BLACKLIST_FILE + --blacklist-file BLACKLIST_FILE, -b BLACKLIST_FILE Path to a blacklist file, this file contains a separate regex exclude on each newline - --whitelist_file WHITELIST_FILE, -w WHITELIST_FILE + --whitelist-file WHITELIST_FILE, -w WHITELIST_FILE Path to a whitelist file, this file contains a separate regex on each newline --regex REGEX, -r REGEX - A normal testr selection regex. If a blacklist file is - specified, the regex will be appended to the end of - the generated regex from that file + A normal testr selection regex. + + --black-regex BLACK_REGEX, -B BLACK_REGEX + Test rejection regex. If the test cases durring a + search opration matches, it will be removed from the + final test list. --pretty, -p Print pretty output from subunit-trace. This is mutually exclusive with --subunit @@ -109,14 +112,29 @@ Test Selection -------------- -ostestr is designed to build on top of the test selection in testr. testr only -exposed a regex option to select tests. This equivalent is functionality is +ostestr intially designed to build on top of the test selection in testr. +testr only exposed a regex option to select tests. This functionality is exposed via the --regex option. For example:: $ ostestr --regex 'magic\.regex' This will do a straight passthrough of the provided regex to testr. -Additionally, ostestr allows you to specify a blacklist file to define a set +When ostestr is asked to do more complex test selection than a sinlge regex, +it will ask testr for a full list of tests than passing the filtered test list +back to testr. +ostestr allows you do to do simple test exclusion via apssing rejection/black regexp:: + + $ ostestr --back-regex 'slow_tests|bad_tests' + +ostestr also allow you to combine these argumants:: + + $ ostestr --regex ui\.interface --back-regexp 'slow_tests|bad_tests' + +Here first we selected all tests which matches to 'ui\.interface', +than we are dropping all test which matches +'slow_tests|bad_tests' from the final list. + +ostestr also allows you to specify a blacklist file to define a set of regexes to exclude. You can specify a blacklist file with the --blacklist_file/-b option, for example:: @@ -129,17 +147,19 @@ ^regex1 # Excludes these tests .*regex2 # exclude those tests -Will generate a regex to pass to testr which will exclude both any tests +The regexp used in the blacklist File or passed as argument, will be used +to drop tests from the initial selection list. +Will generate a list which will exclude both any tests matching '^regex1' and '.*regex2'. If a blacklist file is used in conjunction -with the --regex option the regex specified with --regex will be appended to -the generated output from the --blacklist_file. Also it's worth noting that the +with the --regex option the regex specified with --regex will be used for the intial +test selection. Also it's worth noting that the regex test selection options can not be used in conjunction with the --no-discover or --pdb options described in the previous section. This is because the regex selection requires using testr under the covers to actually do the filtering, and those 2 options do not use testr. -The dual of the blacklist file is the whitelist file which works in the exact -same manner, except that instead of excluding regex matches it includes them. +The dual of the blacklist file is the whitelist file which altering the initial +test selection regex, by joining the white list elements by '|'. You can specify the path to the file with --whitelist_file/-w, for example:: $ ostestr --whitelist_file $path_to_file @@ -150,9 +170,7 @@ ^regex1 # Include these tests .*regex2 # include those tests -However, instead of excluding the matches it will include them. Note that a -blacklist file can not be used at the same time as a whitelist file, they -are mutually exclusive. +However, instead of excluding the matches it will include them. It's also worth noting that you can use the test list option to dry run any selection arguments you are using. You just need to use --list/-l with your @@ -217,13 +235,14 @@ -------------------------- If you use `tox`_ for running your tests and call ostestr as the test command -.. _tox: https://tox.readthedocs.org/en/latest/ it's recommended that you set a posargs following ostestr on the commands - stanza. For example:: +stanza. For example:: [testenv] commands = ostestr {posargs} +.. _tox: https://tox.readthedocs.org/en/latest/ + this will enable end users to pass args to configure the output, use the selection logic, or any other options directly from the tox cli. This will let tox take care of the venv management and the environment separation but enable diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/doc/source/todo.rst new/os-testr-0.8.0/doc/source/todo.rst --- old/os-testr-0.7.0/doc/source/todo.rst 2016-05-26 21:42:56.000000000 +0200 +++ new/os-testr-0.8.0/doc/source/todo.rst 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -.. include:: ../../TODO.rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/doc/source/usage.rst new/os-testr-0.8.0/doc/source/usage.rst --- old/os-testr-0.7.0/doc/source/usage.rst 2016-05-26 21:42:56.000000000 +0200 +++ new/os-testr-0.8.0/doc/source/usage.rst 2016-09-28 21:24:04.000000000 +0200 @@ -10,3 +10,4 @@ ostestr subunit_trace subunit2html + generate_subunit diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/os_testr/ostestr.py new/os-testr-0.8.0/os_testr/ostestr.py --- old/os-testr-0.7.0/os_testr/ostestr.py 2016-05-26 21:42:58.000000000 +0200 +++ new/os-testr-0.8.0/os_testr/ostestr.py 2016-09-28 21:24:04.000000000 +0200 @@ -14,16 +14,19 @@ # under the License. import argparse +import atexit import copy import os import subprocess import sys +import tempfile import pbr.version from subunit import run as subunit_run from testtools import run as testtools_run from os_testr import regex_builder as rb +from os_testr import testlist_builder as tlb __version__ = pbr.version.VersionInfo('os_testr').version_string() @@ -34,20 +37,16 @@ description='Tool to run openstack tests') parser.add_argument('--version', action='version', version='%s' % __version__) - list_files = parser.add_mutually_exclusive_group() - list_files.add_argument('--blacklist_file', '-b', - help='Path to a blacklist file, this file ' - 'contains a separate regex exclude on each ' - 'newline') - list_files.add_argument('--whitelist_file', '-w', - help='Path to a whitelist file, this file ' - 'contains a separate regex on each newline.') + parser.add_argument('--blacklist-file', '-b', '--blacklist_file', + help='Path to a blacklist file, this file ' + 'contains a separate regex exclude on each ' + 'newline') + parser.add_argument('--whitelist-file', '-w', '--whitelist_file', + help='Path to a whitelist file, this file ' + 'contains a separate regex on each newline.') group = parser.add_mutually_exclusive_group() group.add_argument('--regex', '-r', - help='A normal testr selection regex. If a blacklist ' - 'file is specified, the regex will be appended ' - 'to the end of the generated regex from that ' - 'file.') + help='A normal testr selection regex.') group.add_argument('--path', metavar='FILE_OR_DIRECTORY', help='A file name or directory of tests to run.') group.add_argument('--no-discover', '-n', metavar='TEST_ID', @@ -55,6 +54,14 @@ "discover and just execute the test specified. " "A file name may be used in place of a test " "name.") + parser.add_argument('--black-regex', '-B', + help='Test rejection regex. If a test cases name ' + 'matches on re.search() operation , ' + 'it will be removed from the final test list. ' + 'Effectively the black-regexp is added to ' + ' black regexp list, but you do need to edit a file. ' + 'The black filtering happens after the initial ' + ' white selection, which by default is everything.') pretty = parser.add_mutually_exclusive_group() pretty.add_argument('--pretty', '-p', dest='pretty', action='store_true', help='Print pretty output from subunit-trace. This is ' @@ -98,7 +105,7 @@ def call_testr(regex, subunit, pretty, list_tests, slowest, parallel, concur, - until_failure, color, others=None): + until_failure, color, list_of_tests=None, others=None): others = others or [] if parallel: cmd = ['testr', 'run', '--parallel'] @@ -112,7 +119,16 @@ cmd.append('--subunit') elif not (subunit or pretty) and until_failure: cmd.append('--until-failure') - cmd.append(regex) + if list_of_tests: + test_fd, test_file_name = tempfile.mkstemp() + atexit.register(os.remove, test_file_name) + test_file = os.fdopen(test_fd, 'w') + test_file.write('\n'.join(list_of_tests) + '\n') + test_file.close() + cmd.extend(('--load-list', test_file_name)) + elif regex: + cmd.append(regex) + env = copy.deepcopy(os.environ) if pretty: @@ -128,7 +144,7 @@ failed = False if not test_list: print("No tests to run") - exit(1) + return 1 # If pretty or subunit output is desired manually loop forever over # test individually and generate the desired output in a linear series # this avoids 1411804 while retaining most of the desired behavior @@ -152,13 +168,13 @@ except SystemExit as e: if e > 0: print("Ran %s tests without failure" % count) - exit(1) + return 1 else: raise count = count + 1 if failed: print("Ran %s tests without failure" % count) - exit(0) + return 0 # If not until-failure special case call testr like normal elif pretty and not list_tests: cmd.extend(others) @@ -194,15 +210,19 @@ testtools_run.main([sys.argv[0], test_id], sys.stdout) -def _select_and_call_runner(opts, exclude_regex, others): - ec = 1 +def _ensure_testr(): if not os.path.isdir('.testrepository'): subprocess.call(['testr', 'init']) + +def _select_and_call_runner(opts, exclude_regex, others): + ec = 1 + _ensure_testr() + if not opts.no_discover and not opts.pdb: ec = call_testr(exclude_regex, opts.subunit, opts.pretty, opts.list, opts.slowest, opts.parallel, opts.concurrency, - opts.until_failure, opts.color, others) + opts.until_failure, opts.color, None, others) else: if others: print('Unexpected arguments: ' + ' '.join(others)) @@ -214,35 +234,68 @@ return ec -def main(): - opts, others = get_parser(sys.argv[1:]) +def _call_testr_with_list(opts, test_list, others): + ec = 1 + _ensure_testr() + + if opts.list: + print("\n".join(test_list)) + return 0 + + ec = call_testr(None, opts.subunit, opts.pretty, opts.list, + opts.slowest, opts.parallel, opts.concurrency, + opts.until_failure, opts.color, test_list, others) + return ec + + +def ostestr(args): + opts, others = get_parser(args) if opts.pretty and opts.subunit: msg = ('Subunit output and pretty output cannot be specified at the ' 'same time') print(msg) - exit(2) + return 2 if opts.list and opts.no_discover: msg = ('you can not list tests when you are bypassing discovery to ' 'run a single test') print(msg) - exit(3) + return 3 if not opts.parallel and opts.concurrency: msg = "You can't specify a concurrency to use when running serially" print(msg) - exit(4) + return 4 if (opts.pdb or opts.no_discover) and opts.until_failure: msg = "You can not use until_failure mode with pdb or no-discover" print(msg) - exit(5) + return 5 + if ((opts.pdb or opts.no_discover) and + (opts.blacklist_file or opts.whitelist_file)): + msg = "You can not use blacklist or whitelist with pdb or no-discover" + print(msg) + return 6 + if ((opts.pdb or opts.no_discover) and (opts.black_regex)): + msg = "You can not use black-regex with pdb or no-discover" + print(msg) + return 7 + if opts.path: regex = rb.path_to_regex(opts.path) else: regex = opts.regex - exclude_regex = rb.construct_regex(opts.blacklist_file, - opts.whitelist_file, - regex, - opts.print_exclude) - exit(_select_and_call_runner(opts, exclude_regex, others)) + + if opts.blacklist_file or opts.whitelist_file or opts.black_regex: + list_of_tests = tlb.construct_list(opts.blacklist_file, + opts.whitelist_file, + regex, + opts.black_regex, + opts.print_exclude) + return (_call_testr_with_list(opts, list_of_tests, others)) + else: + return (_select_and_call_runner(opts, regex, others)) + + +def main(): + exit(ostestr(sys.argv[1:])) if __name__ == '__main__': main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/os_testr/regex_builder.py new/os-testr-0.8.0/os_testr/regex_builder.py --- old/os-testr-0.7.0/os_testr/regex_builder.py 2016-05-26 21:42:58.000000000 +0200 +++ new/os-testr-0.8.0/os_testr/regex_builder.py 2016-09-28 21:24:05.000000000 +0200 @@ -20,7 +20,7 @@ def _get_test_list(regex, env=None): env = env or copy.deepcopy(os.environ) proc = subprocess.Popen(['testr', 'list-tests', regex], env=env, - stdout=subprocess.PIPE) + stdout=subprocess.PIPE, universal_newlines=True) out = proc.communicate()[0] raw_test_list = out.split('\n') bad = False @@ -29,10 +29,7 @@ 'subunit.run discover'] for line in raw_test_list: for exclude in exclude_list: - if exclude in line: - bad = True - break - elif not line: + if exclude in line or not line: bad = True break if not bad: @@ -71,6 +68,7 @@ def construct_regex(blacklist_file, whitelist_file, regex, print_exclude): + """Deprecated, please use testlist_builder.construct_list instead.""" if not blacklist_file: exclude_regex = '' else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/os_testr/subunit2html.py new/os-testr-0.8.0/os_testr/subunit2html.py --- old/os-testr-0.7.0/os_testr/subunit2html.py 2016-05-26 21:42:56.000000000 +0200 +++ new/os-testr-0.8.0/os_testr/subunit2html.py 2016-09-28 21:24:04.000000000 +0200 @@ -617,8 +617,12 @@ # unittest does not seems to run in any particular order. # Here at least we want to group them together by class. rmap = {} - classes = [] + # Differentiate between classes that have test failures so we can sort + # them at the top of the html page for easier troubleshooting + failclasses = [] + passclasses = [] for n, t, o, e in result_list: + classes = failclasses if n == 1 or n == 2 else passclasses if hasattr(t, '_tests'): for inner_test in t._tests: self._add_cls(rmap, classes, inner_test, @@ -626,7 +630,9 @@ else: self._add_cls(rmap, classes, t, (n, t, o, e)) classort = lambda s: str(s) - sortedclasses = sorted(classes, key=classort) + sortedfailclasses = sorted(failclasses, key=classort) + sortedpassclasses = sorted(passclasses, key=classort) + sortedclasses = sortedfailclasses + sortedpassclasses r = [(cls, rmap[str(cls)]) for cls in sortedclasses] return r diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/os_testr/subunit_trace.py new/os-testr-0.8.0/os_testr/subunit_trace.py --- old/os-testr-0.7.0/os_testr/subunit_trace.py 2016-05-26 21:42:58.000000000 +0200 +++ new/os-testr-0.8.0/os_testr/subunit_trace.py 2016-09-28 21:24:04.000000000 +0200 @@ -180,7 +180,7 @@ color = color(stream) break - if status == 'fail': + if status == 'fail' or status == 'uxsuccess': FAILS.append(test) if abbreviate: color.write('F', 'red') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/os_testr/testlist_builder.py new/os-testr-0.8.0/os_testr/testlist_builder.py --- old/os-testr-0.7.0/os_testr/testlist_builder.py 1970-01-01 01:00:00.000000000 +0100 +++ new/os-testr-0.8.0/os_testr/testlist_builder.py 2016-09-28 21:24:05.000000000 +0200 @@ -0,0 +1,107 @@ +# Copyright 2016 RedHat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from os_testr import regex_builder +import re + + +def black_reader(blacklist_file): + black_file = open(blacklist_file, 'r') + regex_comment_lst = [] # tupple of (regex_compild, msg, skipped_lst) + for line in black_file: + raw_line = line.strip() + split_line = raw_line.split('#') + # Before the # is the regex + line_regex = split_line[0].strip() + if len(split_line) > 1: + # After the # is a comment + comment = ''.join(split_line[1:]).strip() + else: + comment = 'Skipped because of regex %s:' % line_regex + if not line_regex: + continue + regex_comment_lst.append((re.compile(line_regex), comment, [])) + return regex_comment_lst + + +def print_skips(regex, message, test_list): + for test in test_list: + print(test) + # Extra whitespace to separate + print('\n') + + +def construct_list(blacklist_file, whitelist_file, regex, black_regex, + print_exclude): + """Filters the discovered test cases + + :retrun: iterable of strings. The strings are full + test cases names, including tags like.: + "project.api.TestClass.test_case[positive]" + """ + + if not regex: + regex = '' # handle the other false things + + if whitelist_file: + white_re = regex_builder.get_regex_from_whitelist_file(whitelist_file) + else: + white_re = '' + + if not regex and white_re: + regex = white_re + elif regex and white_re: + regex = '|'.join((regex, white_re)) + + if blacklist_file: + black_data = black_reader(blacklist_file) + else: + black_data = None + + if black_regex: + msg = "Skipped bacuse of regexp provided as a command line argument:" + record = (re.compile(black_regex), msg, []) + if black_data: + black_data.append(record) + else: + black_data = [record] + + search_filter = re.compile(regex) + + # NOTE(afazekas): we do not want to pass a giant re + # to an external application due to the arg length limitatios + list_of_test_cases = [test_case for test_case in + regex_builder._get_test_list('') + if search_filter.search(test_case)] + set_of_test_cases = set(list_of_test_cases) + + if not black_data: + return set_of_test_cases + + # NOTE(afazekas): We might use a faster logic when the + # print option is not requested + for (rex, msg, s_list) in black_data: + for test_case in list_of_test_cases: + if rex.search(test_case): + # NOTE(mtreinish): In the case of overlapping regex the test + # case might have already been removed from the set of tests + if test_case in set_of_test_cases: + set_of_test_cases.remove(test_case) + s_list.append(test_case) + + if print_exclude: + for (rex, msg, s_list) in black_data: + if s_list: + print_skips(rex, msg, s_list) + return set_of_test_cases diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/os_testr/tests/test_regex_builder.py new/os-testr-0.8.0/os_testr/tests/test_regex_builder.py --- old/os-testr-0.7.0/os_testr/tests/test_regex_builder.py 2016-05-26 21:42:58.000000000 +0200 +++ new/os-testr-0.8.0/os_testr/tests/test_regex_builder.py 2016-09-28 21:24:05.000000000 +0200 @@ -168,3 +168,9 @@ expected_regex = 'regex_a|regex_b' self.assertEqual(result, expected_regex) + + +class TestGetTestList(base.TestCase): + def test__get_test_list(self): + test_list = os_testr._get_test_list('test__get_test_list') + self.assertIn('test__get_test_list', test_list[0]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/os_testr/tests/test_subunit2html.py new/os-testr-0.8.0/os_testr/tests/test_subunit2html.py --- old/os-testr-0.7.0/os_testr/tests/test_subunit2html.py 2016-05-26 21:42:56.000000000 +0200 +++ new/os-testr-0.8.0/os_testr/tests/test_subunit2html.py 2016-09-28 21:24:04.000000000 +0200 @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import sys + from ddt import data from ddt import ddt from subunit import RemotedTestCase @@ -29,3 +31,46 @@ cls_ = [] obj_._add_cls({}, cls_, test_, ()) self.assertEqual("example.path.to.test", cls_[0].name) + + @data(RemotedTestCase, PlaceHolder) + def test_result_sorting(self, test_cls): + tests = [] + for i in range(9): + tests.append(test_cls('example.path.to.test%d.method' % i)) + # addFailure, addError, and addSkip need the real exc_info + try: + raise Exception('fake') + except Exception: + err = sys.exc_info() + obj = subunit2html.HtmlOutput() + obj.addSuccess(tests[3]) + obj.addSuccess(tests[1]) + # example.path.to.test2 has a failure + obj.addFailure(tests[2], err) + obj.addSkip(tests[0], err) + obj.addSuccess(tests[8]) + # example.path.to.test5 has a failure (error) + obj.addError(tests[5], err) + # example.path.to.test4 has a failure + obj.addFailure(tests[4], err) + obj.addSuccess(tests[7]) + # example.path.to.test6 has a failure + obj.addFailure(tests[6], err) + sorted_result = obj._sortResult(obj.result) + # _sortResult returns a list of results of format: + # [(class, [test_result_tuple, ...]), ...] + # sorted by str(class) + # + # Classes with failures (2, 4, 5, and 6) should be sorted separately + # at the top. The rest of the classes should be in sorted order after. + expected_class_order = ['example.path.to.test2', + 'example.path.to.test4', + 'example.path.to.test5', + 'example.path.to.test6', + 'example.path.to.test0', + 'example.path.to.test1', + 'example.path.to.test3', + 'example.path.to.test7', + 'example.path.to.test8'] + for i, r in enumerate(sorted_result): + self.assertEqual(expected_class_order[i], str(r[0])) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/os_testr/tests/testlist_builder.py new/os-testr-0.8.0/os_testr/tests/testlist_builder.py --- old/os-testr-0.7.0/os_testr/tests/testlist_builder.py 1970-01-01 01:00:00.000000000 +0100 +++ new/os-testr-0.8.0/os_testr/tests/testlist_builder.py 2016-09-28 21:24:05.000000000 +0200 @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- + +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import mock +import re + +import six + +from os_testr import testlist_builder as list_builder +from os_testr.tests import base + + +class TestBlackReader(base.TestCase): + def test_black_reader(self): + blacklist_file = six.StringIO() + for i in range(4): + blacklist_file.write('fake_regex_%s\n' % i) + blacklist_file.write('fake_regex_with_note_%s # note\n' % i) + blacklist_file.seek(0) + with mock.patch('six.moves.builtins.open', + return_value=blacklist_file): + result = list_builder.black_reader('fake_path') + self.assertEqual(2 * 4, len(result)) + note_cnt = 0 + # not assuming ordering, mainly just testing the type + for r in result: + self.assertEqual(r[2], []) + if r[1] == 'note': + note_cnt += 1 + self.assertIn('search', dir(r[0])) # like a compiled regexp + self.assertEqual(note_cnt, 4) + + +class TestConstructList(base.TestCase): + def test_simple_re(self): + test_lists = ['fake_test(scen)[tag,bar])', 'fake_test(scen)[egg,foo])'] + with mock.patch('os_testr.regex_builder._get_test_list', + return_value=test_lists): + result = list_builder.construct_list(None, + None, + 'foo', + None, + False) + self.assertEqual(list(result), ['fake_test(scen)[egg,foo])']) + + def test_simple_black_re(self): + test_lists = ['fake_test(scen)[tag,bar])', 'fake_test(scen)[egg,foo])'] + with mock.patch('os_testr.regex_builder._get_test_list', + return_value=test_lists): + result = list_builder.construct_list(None, + None, + None, + 'foo', + False) + self.assertEqual(list(result), ['fake_test(scen)[tag,bar])']) + + def test_blacklist(self): + black_list = [(re.compile('foo'), 'foo not liked', [])] + test_lists = ['fake_test(scen)[tag,bar])', 'fake_test(scen)[egg,foo])'] + with mock.patch('os_testr.regex_builder._get_test_list', + return_value=test_lists): + with mock.patch('os_testr.testlist_builder.black_reader', + return_value=black_list): + result = list_builder.construct_list('file', + None, + 'fake_test', + None, + False) + self.assertEqual(list(result), ['fake_test(scen)[tag,bar])']) + + def test_whitelist(self): + white_list = 'fake_test1|fake_test2' + test_lists = ['fake_test1[tg]', 'fake_test2[tg]', 'fake_test3[tg]'] + white_getter = 'os_testr.regex_builder.get_regex_from_whitelist_file' + with mock.patch('os_testr.regex_builder._get_test_list', + return_value=test_lists): + with mock.patch(white_getter, + return_value=white_list): + result = list_builder.construct_list(None, + 'file', + None, + None, + False) + self.assertEqual(set(result), + set(('fake_test1[tg]', 'fake_test2[tg]'))) + + def test_whitelist_blacklist_re(self): + white_list = 'fake_test1|fake_test2' + test_lists = ['fake_test1[tg]', 'fake_test2[spam]', + 'fake_test3[tg,foo]', 'fake_test4[spam]'] + black_list = [(re.compile('spam'), 'spam not liked', [])] + white_getter = 'os_testr.regex_builder.get_regex_from_whitelist_file' + with mock.patch('os_testr.regex_builder._get_test_list', + return_value=test_lists): + with mock.patch(white_getter, + return_value=white_list): + with mock.patch('os_testr.testlist_builder.black_reader', + return_value=black_list): + result = list_builder.construct_list('black_file', + 'white_file', + 'foo', + None, + False) + self.assertEqual(set(result), + set(('fake_test1[tg]', 'fake_test3[tg,foo]'))) + + def test_overlapping_black_regex(self): + + black_list = [(re.compile('compute.test_keypairs.KeypairsTestV210'), + '', []), + (re.compile('compute.test_keypairs.KeypairsTestV21'), + '', [])] + test_lists = [ + 'compute.test_keypairs.KeypairsTestV210.test_create_keypair', + 'compute.test_keypairs.KeypairsTestV21.test_create_keypair', + 'compute.test_fake.FakeTest.test_fake_test'] + with mock.patch('os_testr.regex_builder._get_test_list', + return_value=test_lists): + with mock.patch('os_testr.testlist_builder.black_reader', + return_value=black_list): + result = list_builder.construct_list('file', + None, + 'fake_test', + None, + False) + self.assertEqual( + list(result), ['compute.test_fake.FakeTest.test_fake_test']) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/os_testr.egg-info/PKG-INFO new/os-testr-0.8.0/os_testr.egg-info/PKG-INFO --- old/os-testr-0.7.0/os_testr.egg-info/PKG-INFO 2016-05-26 21:45:23.000000000 +0200 +++ new/os-testr-0.8.0/os_testr.egg-info/PKG-INFO 2016-09-28 21:26:08.000000000 +0200 @@ -1,8 +1,8 @@ Metadata-Version: 1.1 Name: os-testr -Version: 0.7.0 +Version: 0.8.0 Summary: A testr wrapper to provide functionality for OpenStack projects -Home-page: http://www.openstack.org/ +Home-page: http://docs.openstack.org/developer/os-testr/ Author: OpenStack Author-email: [email protected] License: UNKNOWN @@ -33,6 +33,7 @@ * ``subunit-trace``: an output filter for a subunit stream which provides useful information about the run * ``subunit2html``: generates a test results html page from a subunit stream + * ``generate-subunit``: generate a subunit stream for a single test Platform: UNKNOWN @@ -46,3 +47,4 @@ Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/os_testr.egg-info/SOURCES.txt new/os-testr-0.8.0/os_testr.egg-info/SOURCES.txt --- old/os-testr-0.7.0/os_testr.egg-info/SOURCES.txt 2016-05-26 21:45:24.000000000 +0200 +++ new/os-testr-0.8.0/os_testr.egg-info/SOURCES.txt 2016-09-28 21:26:08.000000000 +0200 @@ -8,7 +8,6 @@ LICENSE MANIFEST.in README.rst -TODO.rst babel.cfg requirements.txt setup.cfg @@ -17,6 +16,7 @@ tox.ini doc/source/conf.py doc/source/contributing.rst +doc/source/generate_subunit.rst doc/source/history.rst doc/source/index.rst doc/source/installation.rst @@ -24,7 +24,6 @@ doc/source/readme.rst doc/source/subunit2html.rst doc/source/subunit_trace.rst -doc/source/todo.rst doc/source/usage.rst os_testr/__init__.py os_testr/generate_subunit.py @@ -32,6 +31,7 @@ os_testr/regex_builder.py os_testr/subunit2html.py os_testr/subunit_trace.py +os_testr/testlist_builder.py os_testr.egg-info/PKG-INFO os_testr.egg-info/SOURCES.txt os_testr.egg-info/dependency_links.txt @@ -47,6 +47,7 @@ os_testr/tests/test_return_codes.py os_testr/tests/test_subunit2html.py os_testr/tests/test_subunit_trace.py +os_testr/tests/testlist_builder.py os_testr/tests/files/__init__.py os_testr/tests/files/failing-tests os_testr/tests/files/passing-tests diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/os_testr.egg-info/pbr.json new/os-testr-0.8.0/os_testr.egg-info/pbr.json --- old/os-testr-0.7.0/os_testr.egg-info/pbr.json 2016-05-26 21:45:23.000000000 +0200 +++ new/os-testr-0.8.0/os_testr.egg-info/pbr.json 2016-09-28 21:26:08.000000000 +0200 @@ -1 +1 @@ -{"is_release": true, "git_version": "e5e11dc"} \ No newline at end of file +{"is_release": true, "git_version": "0de62e3"} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/setup.cfg new/os-testr-0.8.0/setup.cfg --- old/os-testr-0.7.0/setup.cfg 2016-05-26 21:45:24.000000000 +0200 +++ new/os-testr-0.8.0/setup.cfg 2016-09-28 21:26:08.000000000 +0200 @@ -5,7 +5,7 @@ README.rst author = OpenStack author-email = [email protected] -home-page = http://www.openstack.org/ +home-page = http://docs.openstack.org/developer/os-testr/ classifier = Environment :: OpenStack Intended Audience :: Information Technology @@ -17,6 +17,7 @@ Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.4 + Programming Language :: Python :: 3.5 [files] packages = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/test-requirements.txt new/os-testr-0.8.0/test-requirements.txt --- old/os-testr-0.7.0/test-requirements.txt 2016-05-26 21:42:56.000000000 +0200 +++ new/os-testr-0.8.0/test-requirements.txt 2016-09-28 21:24:05.000000000 +0200 @@ -5,9 +5,8 @@ hacking<0.11,>=0.10.2 # Apache-2.0 coverage>=3.6 # Apache-2.0 -discover # BSD -sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD -oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0 +sphinx!=1.3b1,<1.4,>=1.2.1 # BSD +oslosphinx>=4.7.0 # Apache-2.0 oslotest>=1.10.0 # Apache-2.0 testscenarios>=0.4 # Apache-2.0/BSD ddt>=1.0.1 # MIT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/os-testr-0.7.0/tox.ini new/os-testr-0.8.0/tox.ini --- old/os-testr-0.7.0/tox.ini 2016-05-26 21:42:58.000000000 +0200 +++ new/os-testr-0.8.0/tox.ini 2016-09-28 21:24:04.000000000 +0200 @@ -1,6 +1,6 @@ [tox] minversion = 1.6 -envlist = py34,py27,pypy,pep8 +envlist = py35,py34,py27,pypy,pep8 skipsdist = True [testenv] @@ -36,4 +36,4 @@ show-source = True ignore = E123,E125 builtins = _ -exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build +exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
