Skip to content

Commit

Permalink
Merge pull request #688 from arcivanov/issue_685
Browse files Browse the repository at this point in the history
Unittests need to run in the 'build' environment.
  • Loading branch information
arcivanov committed Apr 13, 2020
2 parents 9f71484 + a0a3fbd commit c71a2cc
Show file tree
Hide file tree
Showing 8 changed files with 543 additions and 92 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
#
# This file is part of PyBuilder
#
# Copyright 2011-2020 PyBuilder Team
#
# 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 sys
import unittest

from itest_support import IntegrationTestSupport
from pybuilder.errors import BuildFailedException


class Test(IntegrationTestSupport):
def test(self):
self.write_build_file("""
from pybuilder.core import use_plugin, init
use_plugin("python.core")
use_plugin("python.unittest")
name = "unittest-integration-test"
default_task = "run_unit_tests"
@init
def init (project):
project.build_depends_on("mockito")
""")
self.create_directory("src/main/python")
self.write_file("src/main/python/helloworld.py", r"""import sys
def helloworld(out):
out.write("Hello world of Python\n")
""")
self.create_directory("src/unittest/python")
self.write_file("src/unittest/python/helloworld_tests.py", r"""from mockito import mock, verify
import unittest
from helloworld import helloworld
class HelloWorldTest(unittest.TestCase):
def test_should_issue_hello_world_message(self):
out = mock()
helloworld(out)
verify(out).write("Goodbye world of Python\n")
""")

reactor = self.prepare_reactor()
try:
reactor.build()
except BuildFailedException:
self.assertTrue("mockito" not in sys.modules)


if __name__ == "__main__":
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
#
# This file is part of PyBuilder
#
# Copyright 2011-2020 PyBuilder Team
#
# 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 sys
import unittest

from itest_support import IntegrationTestSupport


class Test(IntegrationTestSupport):
def test(self):
self.write_build_file("""
from pybuilder.core import use_plugin, init
use_plugin("python.core")
use_plugin("python.unittest")
name = "unittest-integration-test"
default_task = "run_unit_tests"
@init
def init (project):
project.build_depends_on("mockito")
""")
self.create_directory("src/main/python")
self.write_file("src/main/python/helloworld.py", r"""import sys
def helloworld(out):
out.write("Hello world of Python\n")
""")
self.create_directory("src/unittest/python")
self.write_file("src/unittest/python/helloworld_tests.py", r"""from mockito import mock, verify
import unittest
from helloworld import helloworld
class HelloWorldTest(unittest.TestCase):
def test_should_issue_hello_world_message(self):
out = mock()
helloworld(out)
verify(out).write("Hello world of Python\n")
""")

reactor = self.prepare_reactor()
reactor.build()

self.assertTrue("mockito" not in sys.modules)


if __name__ == "__main__":
unittest.main()
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# limitations under the License.


from pybuilder.remote import ctx, PipeShutdownError, RemoteObjectPipe, logger, log_to_stderr
from pybuilder.remote import Process, PipeShutdownError, RemoteObjectPipe, logger, log_to_stderr

__all__ = ["RemoteObjectPipe", "start_tool", "Tool", "PipeShutdownError", "logger"]

Expand All @@ -32,7 +32,7 @@ def stop(self, pipe):
pass


def start_tool(tools, group=None, name=None, logging=None):
def start_tool(pyenv, tools, group=None, name=None, logging=None):
"""
Starts a tool process
"""
Expand All @@ -42,7 +42,8 @@ def start_tool(tools, group=None, name=None, logging=None):
logger.setLevel(int(logging))

pipe = RemoteObjectPipe.new_pipe()
proc = ctx.Process(group=group, target=_instrumented_tool, name=name, args=(tools, pipe))
proc = Process(pyenv, group=group, target=_instrumented_tool, name=name, args=(tools, pipe))

try:
proc.start()
finally:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ def stop(self, pipe):
pipe.hide("unittest_tests")


def start_unittest_tool(tools, test_modules, test_method_prefix, logging=0):
def start_unittest_tool(pyenv, tools, test_modules, test_method_prefix, logging=0):
tool = UnitTestTool(test_modules, test_method_prefix)
return start_tool(tools + [tool], name="unittest", logging=logging)
return start_tool(pyenv, tools + [tool], name="unittest", logging=logging)
24 changes: 15 additions & 9 deletions src/main/python/pybuilder/plugins/python/unittest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def init_test_source_directory(project):
project.set_property_if_unset("unittest_module_glob", "*_tests")
project.set_property_if_unset("unittest_file_suffix", None) # deprecated, use unittest_module_glob.
project.set_property_if_unset("unittest_test_method_prefix", None)
project.set_property_if_unset("unittest_python_env", "build")
project.set_property_if_unset("unittest_runner", (
lambda stream: __import__("xmlrunner").XMLTestRunner(output=project.expand_path("$dir_target/reports"),
stream=stream), "_make_result"))
Expand All @@ -59,6 +60,7 @@ def coverage_init(project, logger, reactor):
project.get_property("_coverage_tasks").append(run_unit_tests)
project.get_property("_coverage_config_prefixes")[run_unit_tests] = "ut"
project.set_property("ut_coverage_name", "Python unit test")
# project.set_property("ut_coverage_python_env", project.get_property("unittest_python_env"))


@task
Expand Down Expand Up @@ -88,9 +90,11 @@ def run_tests(project, logger, reactor, execution_prefix, execution_name):
try:
test_method_prefix = project.get_property("%s_test_method_prefix" % execution_prefix)
runner_generator = project.get_property("%s_runner" % execution_prefix)
result, console_out = execute_tests_matching(reactor.tools, runner_generator, logger, test_dir, module_glob,
test_method_prefix,
project.get_property("remote_debug"))
result, console_out = execute_tests_matching(
reactor.python_env_registry[project.get_property("unittest_python_env")],
reactor.tools, runner_generator, logger, test_dir, module_glob,
test_method_prefix,
project.get_property("remote_debug"))

if result.testsRun == 0:
logger.warn("No %s executed.", execution_name)
Expand Down Expand Up @@ -119,12 +123,12 @@ def run_tests(project, logger, reactor, execution_prefix, execution_name):
raise BuildFailedException("Unable to execute %s." % execution_name)


def execute_tests(tools, runner_generator, logger, test_source, suffix, test_method_prefix=None, remote_debug=0):
return execute_tests_matching(tools, runner_generator, logger, test_source, "*{0}".format(suffix),
def execute_tests(pyenv, tools, runner_generator, logger, test_source, suffix, test_method_prefix=None, remote_debug=0):
return execute_tests_matching(pyenv, tools, runner_generator, logger, test_source, "*{0}".format(suffix),
test_method_prefix, remote_debug=remote_debug)


def execute_tests_matching(tools, runner_generator, logger, test_source, file_glob, test_method_prefix=None,
def execute_tests_matching(pyenv, tools, runner_generator, logger, test_source, file_glob, test_method_prefix=None,
remote_debug=0):
output_log_file = StringIO()
try:
Expand All @@ -134,7 +138,7 @@ def execute_tests_matching(tools, runner_generator, logger, test_source, file_gl
_create_runner(runner_generator, output_log_file))

try:
proc, pipe = start_unittest_tool(tools, test_modules, test_method_prefix, logging=remote_debug)
proc, pipe = start_unittest_tool(pyenv, tools, test_modules, test_method_prefix, logging=remote_debug)
try:
pipe.register_remote(runner)
pipe.register_remote_type(unittest.result.TestResult)
Expand All @@ -149,8 +153,10 @@ def execute_tests_matching(tools, runner_generator, logger, test_source, file_gl
try:
proc.join()
finally:
if sys.version_info[:2] >= (3, 7):
try:
proc.close()
except AttributeError:
pass

remote_closed_cause = pipe.remote_close_cause()
if remote_closed_cause is not None:
Expand Down Expand Up @@ -200,7 +206,7 @@ def _instrument_result(logger, result):
old_addFailure = result.addFailure

def startTest(self, test):
self.test_names.append(test)
self.test_names.append(str(test))
self.logger.debug("starting %s", test)
old_startTest(test)

Expand Down
Loading

0 comments on commit c71a2cc

Please sign in to comment.