diff --git a/pavelib/utils/envs.py b/pavelib/utils/envs.py index 14937d21957c0a9014781b068489a3d9c6d712d0..639b92fbe55503283493dfd88a567a21a6e90967 100644 --- a/pavelib/utils/envs.py +++ b/pavelib/utils/envs.py @@ -12,6 +12,7 @@ import memcache from lazy import lazy from path import Path as path from paver.easy import sh +from six.moves import configparser from pavelib.utils.cmd import django_cmd @@ -251,6 +252,22 @@ class Env(object): ) return unicode(value).strip() + @classmethod + def covered_modules(cls): + """ + List the source modules listed in .coveragerc for which coverage + will be measured. + """ + coveragerc = configparser.RawConfigParser() + coveragerc.read(cls.PYTHON_COVERAGERC) + modules = coveragerc.get('run', 'source') + result = [] + for module in modules.split('\n'): + module = module.strip() + if module: + result.append(module) + return result + @lazy def env_tokens(self): """ @@ -295,3 +312,15 @@ class Env(object): Return a dictionary of feature flags configured by the environment. """ return self.env_tokens.get('FEATURES', dict()) + + @classmethod + def rsync_dirs(cls): + """ + List the directories that should be synced during pytest-xdist + execution. Needs to include all modules for which coverage is + measured, not just the tests being run. + """ + result = set() + for module in cls.covered_modules(): + result.add(module.split('/')[0]) + return result diff --git a/pavelib/utils/test/suites/pytest_suite.py b/pavelib/utils/test/suites/pytest_suite.py index ab320f43fe931b12ebcd61555cb198823e6ffaa7..6f2cc120a8e88dcbb8d8fca92a3b783f33d0e749 100644 --- a/pavelib/utils/test/suites/pytest_suite.py +++ b/pavelib/utils/test/suites/pytest_suite.py @@ -119,6 +119,23 @@ class SystemTestSuite(PytestSuite): self.processes = int(self.processes) + def _under_coverage_cmd(self, cmd): + """ + If self.run_under_coverage is True, it returns the arg 'cmd' + altered to be run under coverage. It returns the command + unaltered otherwise. + """ + if self.run_under_coverage: + if self.xdist_ip_addresses: + for module in Env.covered_modules(): + cmd.append('--cov') + cmd.append(module) + else: + cmd.append('--cov') + cmd.append('--cov-report=') + + return cmd + @property def cmd(self): if self.django_toxenv: @@ -148,12 +165,8 @@ class SystemTestSuite(PytestSuite): xdist_string = '--tx ssh=ubuntu@{}//python="source /edx/app/edxapp/edxapp_env; ' \ 'python"//chdir="/edx/app/edxapp/edx-platform"'.format(ip) cmd.append(xdist_string) - already_synced_dirs = set() - for test_path in self.test_id.split(): - test_root_dir = test_path.split('/')[0] - if test_root_dir not in already_synced_dirs: - cmd.append('--rsyncdir {}'.format(test_root_dir)) - already_synced_dirs.add(test_root_dir) + for rsync_dir in Env.rsync_dirs(): + cmd.append('--rsyncdir {}'.format(rsync_dir)) else: if self.processes == -1: cmd.append('-n auto') @@ -256,12 +269,8 @@ class LibTestSuite(PytestSuite): xdist_string = '--tx ssh=ubuntu@{}//python="source /edx/app/edxapp/edxapp_env; ' \ 'python"//chdir="/edx/app/edxapp/edx-platform"'.format(ip) cmd.append(xdist_string) - already_synced_dirs = set() - for test_path in self.test_id.split(): - test_root_dir = test_path.split('/')[0] - if test_root_dir not in already_synced_dirs: - cmd.append('--rsyncdir {}'.format(test_root_dir)) - already_synced_dirs.add(test_root_dir) + for rsync_dir in Env.rsync_dirs(): + cmd.append('--rsyncdir {}'.format(rsync_dir)) if self.eval_attr: cmd.append("-a '{}'".format(self.eval_attr)) @@ -277,7 +286,12 @@ class LibTestSuite(PytestSuite): unaltered otherwise. """ if self.run_under_coverage: - cmd.append('--cov') + if self.xdist_ip_addresses: + for module in Env.covered_modules(): + cmd.append('--cov') + cmd.append(module) + else: + cmd.append('--cov') if self.append_coverage: cmd.append('--cov-append') cmd.append('--cov-report=')