def register_options(cls, register): super(JUnitRun, cls).register_options(register) register('--batch-size', advanced=True, type=int, default=cls._BATCH_ALL, fingerprint=True, help='Run at most this many tests in a single test process.') register('--test', type=list, fingerprint=True, help='Force running of just these tests. Tests can be specified using any of: ' '[classname], [classname]#[methodname], [filename] or [filename]#[methodname]') register('--per-test-timer', type=bool, help='Show progress and timer for each test.') register('--default-concurrency', advanced=True, fingerprint=True, choices=JUnitTests.VALID_CONCURRENCY_OPTS, default=JUnitTests.CONCURRENCY_SERIAL, help='Set the default concurrency mode for running tests not annotated with' ' @TestParallel or @TestSerial.') register('--parallel-threads', advanced=True, type=int, default=0, fingerprint=True, help='Number of threads to run tests in parallel. 0 for autoset.') register('--test-shard', advanced=True, fingerprint=True, help='Subset of tests to run, in the form M/N, 0 <= M < N. ' 'For example, 1/3 means run tests number 2, 5, 8, 11, ...') register('--output-mode', choices=['ALL', 'FAILURE_ONLY', 'NONE'], default='NONE', help='Specify what part of output should be passed to stdout. ' 'In case of FAILURE_ONLY and parallel tests execution ' 'output can be partial or even wrong. ' 'All tests output also redirected to files in .pants.d/test/junit.') register('--cwd', advanced=True, fingerprint=True, help='Set the working directory. If no argument is passed, use the build root. ' 'If cwd is set on a target, it will supersede this option. It is an error to ' 'use this option in combination with `--chroot`') register('--strict-jvm-version', type=bool, advanced=True, fingerprint=True, help='If true, will strictly require running junits with the same version of java as ' 'the platform -target level. Otherwise, the platform -target level will be ' 'treated as the minimum jvm to run.') register('--failure-summary', type=bool, default=True, help='If true, includes a summary of which test-cases failed at the end of a failed ' 'junit run.') register('--allow-empty-sources', type=bool, advanced=True, fingerprint=True, help='Allows a junit_tests() target to be defined with no sources. Otherwise,' 'such a target will raise an error during the test run.') register('--use-experimental-runner', type=bool, advanced=True, fingerprint=True, help='Use experimental junit-runner logic for more options for parallelism.') register('--html-report', type=bool, fingerprint=True, help='If true, generate an html summary report of tests that were run.') register('--open', type=bool, help='Attempt to open the html summary report in a browser (implies --html-report)') register('--legacy-report-layout', type=bool, default=False, advanced=True, help='Used to link JUnit and coverage reports to the legacy location; now does ' 'nothing.', removal_version='1.8.0.dev0', removal_hint='This option is no longer used and can be safely removed.') # TODO(jtrobec): Remove direct register when coverage steps are moved to their own subsystem. CodeCoverage.register_junit_options(register, cls.register_jvm_tool)
def _isolation(self, all_targets): run_dir = '_runs' mode_dir = 'isolated' if self._per_target else 'combined' batch_dir = str(self._batch_size) if self._batched else 'all' output_dir = os.path.join(self.workdir, run_dir, Target.identify(all_targets), mode_dir, batch_dir) safe_mkdir(output_dir, clean=False) if self._html_report: junit_html_report = JUnitHtmlReport.create( xml_dir=output_dir, open_report=self.get_options().open, logger=self.context.log, error_on_conflict=True) else: junit_html_report = NoJunitHtmlReport() coverage = CodeCoverage.global_instance().get_coverage_engine( self, output_dir, all_targets, self.execute_java_for_coverage) reports = self.Reports(junit_html_report, coverage) self.context.release_lock() try: yield output_dir, reports, coverage finally: lock_file = '.file_lock' preserve = (run_dir, lock_file) dist_dir = os.path.join( self.get_options().pants_distdir, os.path.relpath(self.workdir, self.get_options().pants_workdir)) with OwnerPrintingInterProcessFileLock( os.path.join(dist_dir, lock_file)): self._link_current_reports(report_dir=output_dir, link_dir=dist_dir, preserve=preserve) if self._legacy_report_layout: deprecated_conditional( predicate=lambda: True, entity_description='[test.junit] legacy_report_layout', stacklevel=3, removal_version='1.6.0.dev0', hint_message= 'Reports are now linked into {} by default; so scripts ' 'and CI jobs should be pointed there and the option ' 'configured to False in pants.ini until such time as ' 'the option is removed.'.format(dist_dir)) # NB: Deposit of the "current" test output in the root workdir (.pants.d/test/junit) is a # defacto public API and so we implement that behavior here to maintain backwards # compatibility for non-pants report file consumers. with OwnerPrintingInterProcessFileLock( os.path.join(self.workdir, lock_file)): self._link_current_reports(report_dir=output_dir, link_dir=self.workdir, preserve=preserve)
def _coverage_engine(self): junit_run = self.prepare_execute(self.context()) with temporary_dir() as output_dir: code_coverage = CodeCoverage.global_instance() yield code_coverage.get_coverage_engine(task=junit_run, output_dir=output_dir, all_targets=[], execute_java=junit_run.execute_java_for_coverage)
def _coverage_engine(self): junit_run = self.prepare_execute(self.context()) with temporary_dir() as output_dir: code_coverage = CodeCoverage.global_instance() yield code_coverage.get_coverage_engine(task=junit_run, output_dir=output_dir, all_targets=[], execute_java=junit_run.execute_java_for_coverage)
def _coverage_engine(self): junit_run = self.prepare_execute(self.context()) with temporary_dir() as output_dir: code_coverage = CodeCoverage.global_instance() source_under_test = self.make_target(spec='tests/java/org/pantsbuild/foo', target_type=JavaLibrary, sources=['Foo.java']) yield code_coverage.get_coverage_engine(task=junit_run, output_dir=output_dir, all_targets=[source_under_test], execute_java=junit_run.execute_java_for_coverage)
def _isolation(self, all_targets): run_dir = '_runs' output_dir = os.path.join(self.workdir, run_dir, Target.identify(all_targets)) safe_mkdir(output_dir, clean=False) if self._html_report: junit_html_report = JUnitHtmlReport.create(output_dir, self.context.log) else: junit_html_report = NoJunitHtmlReport() coverage = CodeCoverage.global_instance().get_coverage_engine( self, output_dir, all_targets, self.execute_java_for_coverage) reports = self.Reports(junit_html_report, coverage) self.context.release_lock() try: yield output_dir, reports, coverage finally: # NB: Deposit of the "current" test output in the root workdir (.pants.d/test/junit) is a # defacto public API and so we implement that behavior here to maintain backwards # compatibility for non-pants report file consumers. # TODO(John Sirois): Deprecate this ~API and provide a stable directory solution for test # output: https://github.com/pantsbuild/pants/issues/3879 lock_file = '.file_lock' with OwnerPrintingInterProcessFileLock( os.path.join(self.workdir, lock_file)): # Kill everything except the isolated `_runs/` dir. for name in os.listdir(self.workdir): path = os.path.join(self.workdir, name) if name not in (run_dir, lock_file): if os.path.isdir(path): safe_rmtree(path) else: os.unlink(path) # Link all the isolated run/ dir contents back up to the stable workdir for name in os.listdir(output_dir): path = os.path.join(output_dir, name) os.symlink(path, os.path.join(self.workdir, name))
def _isolation(self, per_target, all_targets): run_dir = '_runs' mode_dir = 'isolated' if per_target else 'combined' batch_dir = str(self._batch_size) if self._batched else 'all' output_dir = os.path.join(self.workdir, run_dir, Target.identify(all_targets), mode_dir, batch_dir) safe_mkdir(output_dir, clean=False) if self._html_report: junit_html_report = JUnitHtmlReport.create( xml_dir=output_dir, open_report=self.get_options().open, logger=self.context.log, error_on_conflict=self.get_options( ).html_report_error_on_conflict) else: junit_html_report = NoJunitHtmlReport() coverage = CodeCoverage.global_instance().get_coverage_engine( self, output_dir, all_targets, self.execute_java_for_coverage) reports = self.Reports(junit_html_report, coverage) self.context.release_lock() try: yield output_dir, reports, coverage finally: lock_file = '.file_lock' preserve = (run_dir, lock_file) dist_dir = os.path.join( self.get_options().pants_distdir, os.path.relpath(self.workdir, self.get_options().pants_workdir)) with OwnerPrintingInterProcessFileLock( os.path.join(dist_dir, lock_file)): self._link_current_reports(report_dir=output_dir, link_dir=dist_dir, preserve=preserve)
def _isolation(self, per_target, all_targets): run_dir = '_runs' mode_dir = 'isolated' if per_target else 'combined' batch_dir = str(self._batch_size) if self._batched else 'all' output_dir = os.path.join(self.workdir, run_dir, Target.identify(all_targets), mode_dir, batch_dir) safe_mkdir(output_dir, clean=False) if self._html_report: junit_html_report = JUnitHtmlReport.create(xml_dir=output_dir, open_report=self.get_options().open, logger=self.context.log, error_on_conflict=True) else: junit_html_report = NoJunitHtmlReport() coverage = CodeCoverage.global_instance().get_coverage_engine( self, output_dir, all_targets, self.execute_java_for_coverage) reports = self.Reports(junit_html_report, coverage) self.context.release_lock() try: yield output_dir, reports, coverage finally: lock_file = '.file_lock' preserve = (run_dir, lock_file) dist_dir = os.path.join(self.get_options().pants_distdir, os.path.relpath(self.workdir, self.get_options().pants_workdir)) with OwnerPrintingInterProcessFileLock(os.path.join(dist_dir, lock_file)): self._link_current_reports(report_dir=output_dir, link_dir=dist_dir, preserve=preserve)
def register_options(cls, register): super().register_options(register) register( "--batch-size", advanced=True, type=int, default=cls._BATCH_ALL, fingerprint=True, help="Run at most this many tests in a single test process.", ) register( "--test", type=list, fingerprint=True, help="Force running of just these tests. Tests can be specified using any of: " "[classname], [classname]#[methodname], [fully qualified classname], " "[fully qualified classname]#[methodname]. If classname is not fully qualified, " "all matching tests will be run. For example, if `foo.bar.TestClass` and " "`foo.baz.TestClass` exist and `TestClass` is supplied, then both will run.", ) register("--per-test-timer", type=bool, help="Show progress and timer for each test.") register( "--default-concurrency", advanced=True, fingerprint=True, choices=JUnitTests.VALID_CONCURRENCY_OPTS, default=JUnitTests.CONCURRENCY_SERIAL, help="Set the default concurrency mode for running tests not annotated with" " @TestParallel or @TestSerial.", ) register( "--parallel-threads", advanced=True, type=int, default=0, fingerprint=True, help="Number of threads to run tests in parallel. 0 for autoset.", ) register( "--test-shard", advanced=True, fingerprint=True, help="Subset of tests to run, in the form M/N, 0 <= M < N. " "For example, 1/3 means run tests number 2, 5, 8, 11, ...", ) register( "--output-mode", choices=["ALL", "FAILURE_ONLY", "NONE"], default="NONE", help="Specify what part of output should be passed to stdout. " "In case of FAILURE_ONLY and parallel tests execution " "output can be partial or even wrong. " "All tests output also redirected to files in .pants.d/test/junit.", ) register( "--cwd", advanced=True, fingerprint=True, help="Set the working directory. If no argument is passed, use the build root. " "If cwd is set on a target, it will supersede this option. It is an error to " "use this option in combination with `--chroot`", ) register( "--strict-jvm-version", type=bool, advanced=True, fingerprint=True, help="If true, will strictly require running junits with the same version of java as " "the platform -target level. Otherwise, the platform -target level will be " "treated as the minimum jvm to run.", ) register( "--failure-summary", type=bool, default=True, help="If true, includes a summary of which test-cases failed at the end of a failed " "junit run.", ) register( "--allow-empty-sources", type=bool, advanced=True, fingerprint=True, help="Allows a junit_tests() target to be defined with no sources. Otherwise," "such a target will raise an error during the test run.", ) register( "--use-experimental-runner", type=bool, advanced=True, fingerprint=True, help="Use experimental junit-runner logic for more options for parallelism.", ) register( "--html-report", type=bool, fingerprint=True, help="If true, generate an html summary report of tests that were run.", ) register( "--html-report-error-on-conflict", type=bool, default=True, help="If true, error when duplicate test cases are found in html results", ) register( "--open", type=bool, help="Attempt to open the html summary report in a browser (implies --html-report)", ) # TODO(jtrobec): Remove direct register when coverage steps are moved to their own subsystem. CodeCoverage.register_junit_options(register, cls.register_jvm_tool)