From d66e201c3f156b3541c0fa69307b0e83dfe26fa1 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Sat, 30 Nov 2019 17:57:40 +0100 Subject: [PATCH 1/9] test main function with unit tests --- unit_test/main_function_test.py | 263 ++++++++++++++++++++++++++++++++ unit_test/platform_test.py | 59 ------- 2 files changed, 263 insertions(+), 59 deletions(-) create mode 100644 unit_test/main_function_test.py delete mode 100644 unit_test/platform_test.py diff --git a/unit_test/main_function_test.py b/unit_test/main_function_test.py new file mode 100644 index 00000000..d2e48a3f --- /dev/null +++ b/unit_test/main_function_test.py @@ -0,0 +1,263 @@ +import sys +import os +import subprocess + +import pytest + +from cibuildwheel.__main__ import main +from cibuildwheel import windows, linux, macos +from cibuildwheel.util import BuildSelector +from cibuildwheel.environment import ParsedEnvironment + +@pytest.fixture +def argtest(): + class TestArgs(object): + def __call__(self, **kwargs): + self.kwargs = dict(kwargs) + return TestArgs() + +def not_call_mock(*args, **kwargs): + raise RuntimeError("This should never be called") + + +def apply_mock_protection(monkeypatch): + monkeypatch.setattr(subprocess, "Popen", not_call_mock) + monkeypatch.setattr(windows, "urlopen", not_call_mock) + monkeypatch.setattr(windows, "build", not_call_mock) + monkeypatch.setattr(linux, "build", not_call_mock) + monkeypatch.setattr(macos, "build", not_call_mock) + monkeypatch.setattr(os.path, "exists", lambda x: True) + monkeypatch.setattr(sys, "argv", ["python", "abcabc"]) + + +def test_unknown_platform_non_ci(monkeypatch, capsys): + monkeypatch.setattr(os, 'environ', {}) + apply_mock_protection(monkeypatch) + with pytest.raises(SystemExit) as exit: + main() + assert exit.value.code == 2 + _, err = capsys.readouterr() + assert 'cibuildwheel: Unable to detect platform.' in err + assert "cibuildwheel should run on your CI server" in err + + +def test_unknown_platform_on_ci(monkeypatch, capsys): + monkeypatch.setattr(os, 'environ', {"CI": "true"}) + apply_mock_protection(monkeypatch) + monkeypatch.setattr(sys, "platform", "Something") + + with pytest.raises(SystemExit) as exit: + main() + _, err = capsys.readouterr() + assert exit.value.code == 2 + assert 'cibuildwheel: Unable to detect platform from "sys.platform"' in err + + +def test_unknown_platform(monkeypatch, capsys): + monkeypatch.setattr(os, 'environ', {"CIBW_PLATFORM": "Something"}) + apply_mock_protection(monkeypatch) + with pytest.raises(SystemExit) as exit: + main() + _, err = capsys.readouterr() + assert exit.value.code == 2 + assert 'cibuildwheel: Unsupported platform: Something' in err + +@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) +@pytest.mark.parametrize("choose_platform_method", ["partameter", "environment"]) +def test_platform_chose(system, choose_platform_method, argtest, monkeypatch): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(globals()[system], "build", argtest) + if choose_platform_method == "partameter": + monkeypatch.setattr(sys, "argv", sys.argv + ["--platform", system]) + else: + monkeypatch.setattr(os, 'environ', {"CIBW_PLATFORM": system}) + main() + assert argtest.kwargs["project_dir"] == "abcabc" + +@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) +@pytest.mark.parametrize("output_dir", ["partameter", "environment", "both", "none"]) +def test_output_dir_set(system, output_dir, monkeypatch, argtest): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(globals()[system], "build", argtest) + output_name = "out" + env = {"CIBW_PLATFORM": system} + if output_dir == "partameter": + monkeypatch.setattr(sys, "argv", sys.argv + ["--output-dir", output_name]) + elif output_dir == "environment": + env["CIBW_OUTPUT_DIR"] = output_name + elif output_dir == "both": + monkeypatch.setattr(sys, "argv", sys.argv + ["--output-dir", output_name]) + env["CIBW_OUTPUT_DIR"] = output_name + "aaa" + else: + output_name = "wheelhouse" + monkeypatch.setattr(os, 'environ', env) + main() + assert argtest.kwargs["output_dir"] == output_name + +@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) +@pytest.mark.parametrize("build,build_set", [ + ("*", {"aaaa", "abcd", "abab", "bcde"}), + ("a*", {"aaaa", "abcd", "abab"}), + ("*b*", {"abcd", "abab", "bcde"}) + ]) +@pytest.mark.parametrize("skip,skip_set", [ + ("", set()), ("a*", {"aaaa", "abcd", "abab"}), + ("*c*", {"abcd", "bcde"}) +]) +def test_build_selector(system, build, build_set, skip, skip_set, monkeypatch, argtest): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(globals()[system], "build", argtest) + env = {"CIBW_PLATFORM": system, "CIBW_BUILD": build, "CIBW_SKIP": skip} + monkeypatch.setattr(os, 'environ', env) + main() + assert isinstance(argtest.kwargs["build_selector"], BuildSelector) + selector = argtest.kwargs["build_selector"] + selected = set([x for x in ["aaaa", "abcd", "abab", "bcde"] if selector(x)]) + assert selected == build_set.difference(skip_set) + + +@pytest.mark.parametrize("system", ["macos", "windows"]) +@pytest.mark.parametrize("manylinux", ["none", "manylinux1"]) +def test_no_manylinux(system, manylinux, monkeypatch, argtest): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(globals()[system], "build", argtest) + env = {"CIBW_PLATFORM": system} + if manylinux != "none": + env["CIBW_MANYLINUX_I686_IMAGE"] = manylinux + env["CIBW_MANYLINUX_X86_64_IMAGE"] = manylinux + monkeypatch.setattr(os, 'environ', env) + main() + assert "manylinux_images" not in argtest.kwargs + + +@pytest.mark.parametrize("manylinux86,manylinux86_image", [ + ("none", 'quay.io/pypa/manylinux2010_i686'), + ("manylinux1", 'quay.io/pypa/manylinux1_i686'), + ("manylinux2010", 'quay.io/pypa/manylinux2010_i686'), + ("asfsgd", "asfsgd")]) +@pytest.mark.parametrize("manylinux64, manylinux64_image", [ + ("none", 'quay.io/pypa/manylinux2010_x86_64'), + ("manylinux1", 'quay.io/pypa/manylinux1_x86_64'), + ("manylinux2010", 'quay.io/pypa/manylinux2010_x86_64'), + ("asfsgd", "asfsgd")]) +def test_manylinux_choose(manylinux86, manylinux86_image, manylinux64, + manylinux64_image, monkeypatch, argtest): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(linux, "build", argtest) + env = {"CIBW_PLATFORM": "linux"} + if manylinux86 != "none": + env["CIBW_MANYLINUX_I686_IMAGE"] = manylinux86 + if manylinux64 != "none": + env["CIBW_MANYLINUX_X86_64_IMAGE"] = manylinux64 + monkeypatch.setattr(os, 'environ', env) + main() + assert argtest.kwargs["manylinux_images"]['x86_64'] == manylinux64_image + assert argtest.kwargs["manylinux_images"]['i686'] == manylinux86_image + + +@pytest.mark.parametrize("system,default_repair", [ + ("macos", "delocate"), ("linux", "auditwheel"), + ("windows", "")]) +@pytest.mark.parametrize("repair_command", ["none", "aaaa", "repair -w {dest_dir} {wheel}"]) +@pytest.mark.parametrize("system_suffix", (True, False)) +def test_repair_command(system, default_repair, repair_command, system_suffix, monkeypatch, argtest): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(globals()[system], "build", argtest) + env = {"CIBW_PLATFORM": system} + if repair_command != "none": + env["CIBW_REPAIR_WHEEL_COMMAND"] = repair_command + if system_suffix: + env["CIBW_REPAIR_WHEEL_COMMAND_" + system.upper()] = "abcabc" + monkeypatch.setattr(os, 'environ', env) + main() + if system_suffix: + assert argtest.kwargs["repair_command"] == "abcabc" + elif repair_command == "none": + if default_repair: + assert argtest.kwargs["repair_command"].startswith(default_repair) + else: + assert len(argtest.kwargs["repair_command"]) == 0 + else: + assert argtest.kwargs["repair_command"] == repair_command + +@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) +@pytest.mark.parametrize("environment", [{}, {"AAA": "123"}, {"AA1": "124", "AA2": "124"}]) +@pytest.mark.parametrize("platform_environment", [{}, {"BBB": "123"}, {"BB1": "123", "BB2": "127"}]) +def test_environment(system, environment, platform_environment, monkeypatch, argtest): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(globals()[system], "build", argtest) + env = {"CIBW_PLATFORM": system} + cibw_env = " ".join(["{}={}".format(k, v) for k, v in environment.items()]) + platform_env = " ".join(["{}={}".format(k, v) for k, v in platform_environment.items()]) + if cibw_env: + env["CIBW_ENVIRONMENT"] = cibw_env + if platform_env: + env["CIBW_ENVIRONMENT_{}".format(system.upper())] = platform_env + monkeypatch.setattr(os, 'environ', env) + main() + assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) + if platform_environment: + assert argtest.kwargs["environment"].as_dictionary({}) == platform_environment + else: + assert argtest.kwargs["environment"].as_dictionary({}) == environment + + +def identity(x): + return x + + +def extras(x): + if x is None: + return "" + return "[{}]".format(x) + + +def requires(x): + if x is None: + return [] + return x.split() + + +@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) +@pytest.mark.parametrize("generic_var", [None, "test1"]) +@pytest.mark.parametrize("platform_generic_var", [None, "test2"]) +@pytest.mark.parametrize("environ_var,kwargs_var,transform_var", [ + ("CIBW_BEFORE_BUILD", "before_build", identity), ("CIBW_TEST_COMMAND", "test_command", identity), + ("CIBW_TEST_EXTRAS", "test_extras", extras), ("CIBW_TEST_REQUIRES", "test_requires", requires)]) +def test_generic_var(system, generic_var, platform_generic_var, environ_var, kwargs_var, transform_var, monkeypatch, argtest): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(globals()[system], "build", argtest) + env = {"CIBW_PLATFORM": system} + if generic_var: + env[environ_var] = generic_var + if platform_generic_var: + env["{}_{}".format(environ_var, system.upper())] = platform_generic_var + monkeypatch.setattr(os, 'environ', env) + main() + assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) + if platform_generic_var: + assert argtest.kwargs[kwargs_var] == transform_var(platform_generic_var) + else: + assert argtest.kwargs[kwargs_var] == transform_var(generic_var) + + +@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) +@pytest.mark.parametrize("verbosity", [None, 0, -2, 4]) +@pytest.mark.parametrize("platform_verbosity", [None, 0, 2, -4]) +def test_build_verbosity(system, verbosity, platform_verbosity, monkeypatch, argtest): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(globals()[system], "build", argtest) + env = {"CIBW_PLATFORM": system} + if verbosity is not None: + env["CIBW_BUILD_VERBOSITY"] = verbosity + if platform_verbosity is not None: + env["CIBW_BUILD_VERBOSITY_{}".format(system.upper())] = platform_verbosity + monkeypatch.setattr(os, 'environ', env) + main() + assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) + if platform_verbosity is not None: + assert argtest.kwargs["build_verbosity"] == platform_verbosity if platform_verbosity > -4 else -3 + elif verbosity is not None: + assert argtest.kwargs["build_verbosity"] == verbosity if verbosity < 4 else 3 + else: + assert argtest.kwargs["build_verbosity"] == 0 \ No newline at end of file diff --git a/unit_test/platform_test.py b/unit_test/platform_test.py deleted file mode 100644 index f4199cc2..00000000 --- a/unit_test/platform_test.py +++ /dev/null @@ -1,59 +0,0 @@ -import sys -import os -import subprocess - -import pytest - -from cibuildwheel.__main__ import main -from cibuildwheel import windows, linux, macos - - -def not_call_mock(*args, **kwargs): - raise RuntimeError("This should never be called") - - -def apply_mock_protection(monkeypatch): - monkeypatch.setattr(subprocess, "Popen", not_call_mock) - monkeypatch.setattr(windows, "urlopen", not_call_mock) - monkeypatch.setattr(windows, "build", not_call_mock) - monkeypatch.setattr(linux, "build", not_call_mock) - monkeypatch.setattr(macos, "build", not_call_mock) - - -def test_unknown_platform_non_ci(monkeypatch, capsys, tmp_path): - monkeypatch.setattr(os, 'environ', {}) - monkeypatch.setattr(sys, "argv", ["python", str(tmp_path)]) - apply_mock_protection(monkeypatch) - with pytest.raises(SystemExit) as exit: - main() - assert exit.value.code == 2 - _, err = capsys.readouterr() - assert 'cibuildwheel: Unable to detect platform.' in err - assert "cibuildwheel should run on your CI server" in err - - -def test_unknown_platform_on_ci(monkeypatch, capsys, tmp_path): - monkeypatch.setattr(os, 'environ', {"CI": "true"}) - monkeypatch.setattr(sys, "argv", ["python", str(tmp_path)]) - apply_mock_protection(monkeypatch) - monkeypatch.setattr(sys, "platform", "Something") - - with pytest.raises(SystemExit) as exit: - main() - _, err = capsys.readouterr() - assert exit.value.code == 2 - assert 'cibuildwheel: Unable to detect platform from "sys.platform"' in err - - -def test_unknown_platform(monkeypatch, capsys, tmp_path): - monkeypatch.setattr(os, 'environ', {"CIBW_PLATFORM": "Something"}) - monkeypatch.setattr(sys, "argv", ["python", str(tmp_path)]) - apply_mock_protection(monkeypatch) - with open(str(tmp_path / "setup.py"), "w") as f: - f.write('from setuptools import setup\nsetup(name="spam", version="0.1.0",)') - - with pytest.raises(SystemExit) as exit: - main() - _, err = capsys.readouterr() - assert exit.value.code == 2 - assert 'cibuildwheel: Unsupported platform: Something' in err From 0b707b22edc91c3dcdabbf6503732db4f7ebeb5f Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Sun, 15 Dec 2019 14:54:54 +0100 Subject: [PATCH 2/9] split test function on parts to be more readable. --- unit_test/main_function_test.py | 101 +++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 29 deletions(-) diff --git a/unit_test/main_function_test.py b/unit_test/main_function_test.py index d2e48a3f..31f44ebf 100644 --- a/unit_test/main_function_test.py +++ b/unit_test/main_function_test.py @@ -202,43 +202,86 @@ def test_environment(system, environment, platform_environment, monkeypatch, arg assert argtest.kwargs["environment"].as_dictionary({}) == environment -def identity(x): - return x - - -def extras(x): - if x is None: - return "" - return "[{}]".format(x) - - -def requires(x): - if x is None: - return [] - return x.split() - - @pytest.mark.parametrize("system", ["macos", "linux", "windows"]) -@pytest.mark.parametrize("generic_var", [None, "test1"]) -@pytest.mark.parametrize("platform_generic_var", [None, "test2"]) -@pytest.mark.parametrize("environ_var,kwargs_var,transform_var", [ - ("CIBW_BEFORE_BUILD", "before_build", identity), ("CIBW_TEST_COMMAND", "test_command", identity), - ("CIBW_TEST_EXTRAS", "test_extras", extras), ("CIBW_TEST_REQUIRES", "test_requires", requires)]) -def test_generic_var(system, generic_var, platform_generic_var, environ_var, kwargs_var, transform_var, monkeypatch, argtest): +@pytest.mark.parametrize("test_requires", ["", "test1"]) +@pytest.mark.parametrize("platform_test_requires", ["", "test2"]) +def test_test_requires(system, test_requires, platform_test_requires, monkeypatch, argtest): apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) env = {"CIBW_PLATFORM": system} - if generic_var: - env[environ_var] = generic_var - if platform_generic_var: - env["{}_{}".format(environ_var, system.upper())] = platform_generic_var + if test_requires: + env["CIBW_TEST_REQUIRES"] = test_requires + if platform_test_requires: + env["CIBW_TEST_REQUIRES_{}".format(system.upper())] = platform_test_requires monkeypatch.setattr(os, 'environ', env) main() assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) - if platform_generic_var: - assert argtest.kwargs[kwargs_var] == transform_var(platform_generic_var) + if platform_test_requires: + assert argtest.kwargs["test_requires"] == platform_test_requires.split() else: - assert argtest.kwargs[kwargs_var] == transform_var(generic_var) + assert argtest.kwargs["test_requires"] == test_requires.split() + + +@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) +@pytest.mark.parametrize("test_extras", ["", "test1"]) +@pytest.mark.parametrize("platform_test_extras", ["", "test2"]) +def test_test_extras(system, test_extras, platform_test_extras, monkeypatch, argtest): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(globals()[system], "build", argtest) + env = {"CIBW_PLATFORM": system} + if test_extras: + env["CIBW_TEST_EXTRAS"] = test_extras + if platform_test_extras: + env["CIBW_TEST_EXTRAS_{}".format(system.upper())] = platform_test_extras + monkeypatch.setattr(os, 'environ', env) + main() + assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) + if platform_test_extras: + assert argtest.kwargs["test_extras"] == "[" + platform_test_extras + "]" + elif test_extras: + assert argtest.kwargs["test_extras"] == "[" + test_extras + "]" + else: + assert argtest.kwargs["test_extras"] == "" + + +@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) +@pytest.mark.parametrize("test_command", [None, "test1"]) +@pytest.mark.parametrize("platform_test_command", [None, "test2"]) +def test_test_command(system, test_command, platform_test_command, monkeypatch, argtest): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(globals()[system], "build", argtest) + env = {"CIBW_PLATFORM": system} + if test_command: + env["CIBW_TEST_COMMAND"] = test_command + if platform_test_command: + env["CIBW_TEST_COMMAND_{}".format(system.upper())] = platform_test_command + monkeypatch.setattr(os, 'environ', env) + main() + assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) + if platform_test_command: + assert argtest.kwargs["test_command"] == platform_test_command + else: + assert argtest.kwargs["test_command"] == test_command + + +@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) +@pytest.mark.parametrize("before_build", [None, "test1"]) +@pytest.mark.parametrize("platform_before_build", [None, "test2"]) +def test_before_build(system, before_build, platform_before_build, monkeypatch, argtest): + apply_mock_protection(monkeypatch) + monkeypatch.setattr(globals()[system], "build", argtest) + env = {"CIBW_PLATFORM": system} + if before_build: + env["CIBW_BEFORE_BUILD"] = before_build + if platform_before_build: + env["CIBW_BEFORE_BUILD_{}".format(system.upper())] = platform_before_build + monkeypatch.setattr(os, 'environ', env) + main() + assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) + if platform_before_build: + assert argtest.kwargs["before_build"] == platform_before_build + else: + assert argtest.kwargs["before_build"] == before_build @pytest.mark.parametrize("system", ["macos", "linux", "windows"]) From 5e330112295fbc22472b53c4306b91592bda3925 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Sun, 15 Dec 2019 15:38:54 +0100 Subject: [PATCH 3/9] remove apply_mock_protection by making it fixture --- unit_test/main_function_test.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/unit_test/main_function_test.py b/unit_test/main_function_test.py index 31f44ebf..baff2cac 100644 --- a/unit_test/main_function_test.py +++ b/unit_test/main_function_test.py @@ -20,6 +20,7 @@ def not_call_mock(*args, **kwargs): raise RuntimeError("This should never be called") +@pytest.fixture(autouse=True) def apply_mock_protection(monkeypatch): monkeypatch.setattr(subprocess, "Popen", not_call_mock) monkeypatch.setattr(windows, "urlopen", not_call_mock) @@ -32,7 +33,6 @@ def apply_mock_protection(monkeypatch): def test_unknown_platform_non_ci(monkeypatch, capsys): monkeypatch.setattr(os, 'environ', {}) - apply_mock_protection(monkeypatch) with pytest.raises(SystemExit) as exit: main() assert exit.value.code == 2 @@ -43,7 +43,6 @@ def test_unknown_platform_non_ci(monkeypatch, capsys): def test_unknown_platform_on_ci(monkeypatch, capsys): monkeypatch.setattr(os, 'environ', {"CI": "true"}) - apply_mock_protection(monkeypatch) monkeypatch.setattr(sys, "platform", "Something") with pytest.raises(SystemExit) as exit: @@ -55,7 +54,6 @@ def test_unknown_platform_on_ci(monkeypatch, capsys): def test_unknown_platform(monkeypatch, capsys): monkeypatch.setattr(os, 'environ', {"CIBW_PLATFORM": "Something"}) - apply_mock_protection(monkeypatch) with pytest.raises(SystemExit) as exit: main() _, err = capsys.readouterr() @@ -65,7 +63,6 @@ def test_unknown_platform(monkeypatch, capsys): @pytest.mark.parametrize("system", ["macos", "linux", "windows"]) @pytest.mark.parametrize("choose_platform_method", ["partameter", "environment"]) def test_platform_chose(system, choose_platform_method, argtest, monkeypatch): - apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) if choose_platform_method == "partameter": monkeypatch.setattr(sys, "argv", sys.argv + ["--platform", system]) @@ -77,7 +74,6 @@ def test_platform_chose(system, choose_platform_method, argtest, monkeypatch): @pytest.mark.parametrize("system", ["macos", "linux", "windows"]) @pytest.mark.parametrize("output_dir", ["partameter", "environment", "both", "none"]) def test_output_dir_set(system, output_dir, monkeypatch, argtest): - apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) output_name = "out" env = {"CIBW_PLATFORM": system} @@ -105,7 +101,6 @@ def test_output_dir_set(system, output_dir, monkeypatch, argtest): ("*c*", {"abcd", "bcde"}) ]) def test_build_selector(system, build, build_set, skip, skip_set, monkeypatch, argtest): - apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) env = {"CIBW_PLATFORM": system, "CIBW_BUILD": build, "CIBW_SKIP": skip} monkeypatch.setattr(os, 'environ', env) @@ -119,7 +114,6 @@ def test_build_selector(system, build, build_set, skip, skip_set, monkeypatch, a @pytest.mark.parametrize("system", ["macos", "windows"]) @pytest.mark.parametrize("manylinux", ["none", "manylinux1"]) def test_no_manylinux(system, manylinux, monkeypatch, argtest): - apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) env = {"CIBW_PLATFORM": system} if manylinux != "none": @@ -142,7 +136,6 @@ def test_no_manylinux(system, manylinux, monkeypatch, argtest): ("asfsgd", "asfsgd")]) def test_manylinux_choose(manylinux86, manylinux86_image, manylinux64, manylinux64_image, monkeypatch, argtest): - apply_mock_protection(monkeypatch) monkeypatch.setattr(linux, "build", argtest) env = {"CIBW_PLATFORM": "linux"} if manylinux86 != "none": @@ -161,7 +154,6 @@ def test_manylinux_choose(manylinux86, manylinux86_image, manylinux64, @pytest.mark.parametrize("repair_command", ["none", "aaaa", "repair -w {dest_dir} {wheel}"]) @pytest.mark.parametrize("system_suffix", (True, False)) def test_repair_command(system, default_repair, repair_command, system_suffix, monkeypatch, argtest): - apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) env = {"CIBW_PLATFORM": system} if repair_command != "none": @@ -184,7 +176,6 @@ def test_repair_command(system, default_repair, repair_command, system_suffix, m @pytest.mark.parametrize("environment", [{}, {"AAA": "123"}, {"AA1": "124", "AA2": "124"}]) @pytest.mark.parametrize("platform_environment", [{}, {"BBB": "123"}, {"BB1": "123", "BB2": "127"}]) def test_environment(system, environment, platform_environment, monkeypatch, argtest): - apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) env = {"CIBW_PLATFORM": system} cibw_env = " ".join(["{}={}".format(k, v) for k, v in environment.items()]) @@ -206,7 +197,6 @@ def test_environment(system, environment, platform_environment, monkeypatch, arg @pytest.mark.parametrize("test_requires", ["", "test1"]) @pytest.mark.parametrize("platform_test_requires", ["", "test2"]) def test_test_requires(system, test_requires, platform_test_requires, monkeypatch, argtest): - apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) env = {"CIBW_PLATFORM": system} if test_requires: @@ -226,7 +216,6 @@ def test_test_requires(system, test_requires, platform_test_requires, monkeypatc @pytest.mark.parametrize("test_extras", ["", "test1"]) @pytest.mark.parametrize("platform_test_extras", ["", "test2"]) def test_test_extras(system, test_extras, platform_test_extras, monkeypatch, argtest): - apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) env = {"CIBW_PLATFORM": system} if test_extras: @@ -248,7 +237,6 @@ def test_test_extras(system, test_extras, platform_test_extras, monkeypatch, arg @pytest.mark.parametrize("test_command", [None, "test1"]) @pytest.mark.parametrize("platform_test_command", [None, "test2"]) def test_test_command(system, test_command, platform_test_command, monkeypatch, argtest): - apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) env = {"CIBW_PLATFORM": system} if test_command: @@ -268,7 +256,6 @@ def test_test_command(system, test_command, platform_test_command, monkeypatch, @pytest.mark.parametrize("before_build", [None, "test1"]) @pytest.mark.parametrize("platform_before_build", [None, "test2"]) def test_before_build(system, before_build, platform_before_build, monkeypatch, argtest): - apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) env = {"CIBW_PLATFORM": system} if before_build: @@ -288,7 +275,6 @@ def test_before_build(system, before_build, platform_before_build, monkeypatch, @pytest.mark.parametrize("verbosity", [None, 0, -2, 4]) @pytest.mark.parametrize("platform_verbosity", [None, 0, 2, -4]) def test_build_verbosity(system, verbosity, platform_verbosity, monkeypatch, argtest): - apply_mock_protection(monkeypatch) monkeypatch.setattr(globals()[system], "build", argtest) env = {"CIBW_PLATFORM": system} if verbosity is not None: From 05e78588150cc4746f3b3c8eb9904af7413bf4c7 Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Sun, 15 Dec 2019 20:28:38 +0100 Subject: [PATCH 4/9] Refactoring main_function_test.py --- unit_test/main_function_test.py | 292 -------------------------------- unit_test/main_options_test.py | 203 ++++++++++++++++++++++ unit_test/main_platform_test.py | 59 +++++++ unit_test/main_util_fixtures.py | 43 +++++ 4 files changed, 305 insertions(+), 292 deletions(-) delete mode 100644 unit_test/main_function_test.py create mode 100644 unit_test/main_options_test.py create mode 100644 unit_test/main_platform_test.py create mode 100644 unit_test/main_util_fixtures.py diff --git a/unit_test/main_function_test.py b/unit_test/main_function_test.py deleted file mode 100644 index baff2cac..00000000 --- a/unit_test/main_function_test.py +++ /dev/null @@ -1,292 +0,0 @@ -import sys -import os -import subprocess - -import pytest - -from cibuildwheel.__main__ import main -from cibuildwheel import windows, linux, macos -from cibuildwheel.util import BuildSelector -from cibuildwheel.environment import ParsedEnvironment - -@pytest.fixture -def argtest(): - class TestArgs(object): - def __call__(self, **kwargs): - self.kwargs = dict(kwargs) - return TestArgs() - -def not_call_mock(*args, **kwargs): - raise RuntimeError("This should never be called") - - -@pytest.fixture(autouse=True) -def apply_mock_protection(monkeypatch): - monkeypatch.setattr(subprocess, "Popen", not_call_mock) - monkeypatch.setattr(windows, "urlopen", not_call_mock) - monkeypatch.setattr(windows, "build", not_call_mock) - monkeypatch.setattr(linux, "build", not_call_mock) - monkeypatch.setattr(macos, "build", not_call_mock) - monkeypatch.setattr(os.path, "exists", lambda x: True) - monkeypatch.setattr(sys, "argv", ["python", "abcabc"]) - - -def test_unknown_platform_non_ci(monkeypatch, capsys): - monkeypatch.setattr(os, 'environ', {}) - with pytest.raises(SystemExit) as exit: - main() - assert exit.value.code == 2 - _, err = capsys.readouterr() - assert 'cibuildwheel: Unable to detect platform.' in err - assert "cibuildwheel should run on your CI server" in err - - -def test_unknown_platform_on_ci(monkeypatch, capsys): - monkeypatch.setattr(os, 'environ', {"CI": "true"}) - monkeypatch.setattr(sys, "platform", "Something") - - with pytest.raises(SystemExit) as exit: - main() - _, err = capsys.readouterr() - assert exit.value.code == 2 - assert 'cibuildwheel: Unable to detect platform from "sys.platform"' in err - - -def test_unknown_platform(monkeypatch, capsys): - monkeypatch.setattr(os, 'environ', {"CIBW_PLATFORM": "Something"}) - with pytest.raises(SystemExit) as exit: - main() - _, err = capsys.readouterr() - assert exit.value.code == 2 - assert 'cibuildwheel: Unsupported platform: Something' in err - -@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) -@pytest.mark.parametrize("choose_platform_method", ["partameter", "environment"]) -def test_platform_chose(system, choose_platform_method, argtest, monkeypatch): - monkeypatch.setattr(globals()[system], "build", argtest) - if choose_platform_method == "partameter": - monkeypatch.setattr(sys, "argv", sys.argv + ["--platform", system]) - else: - monkeypatch.setattr(os, 'environ', {"CIBW_PLATFORM": system}) - main() - assert argtest.kwargs["project_dir"] == "abcabc" - -@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) -@pytest.mark.parametrize("output_dir", ["partameter", "environment", "both", "none"]) -def test_output_dir_set(system, output_dir, monkeypatch, argtest): - monkeypatch.setattr(globals()[system], "build", argtest) - output_name = "out" - env = {"CIBW_PLATFORM": system} - if output_dir == "partameter": - monkeypatch.setattr(sys, "argv", sys.argv + ["--output-dir", output_name]) - elif output_dir == "environment": - env["CIBW_OUTPUT_DIR"] = output_name - elif output_dir == "both": - monkeypatch.setattr(sys, "argv", sys.argv + ["--output-dir", output_name]) - env["CIBW_OUTPUT_DIR"] = output_name + "aaa" - else: - output_name = "wheelhouse" - monkeypatch.setattr(os, 'environ', env) - main() - assert argtest.kwargs["output_dir"] == output_name - -@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) -@pytest.mark.parametrize("build,build_set", [ - ("*", {"aaaa", "abcd", "abab", "bcde"}), - ("a*", {"aaaa", "abcd", "abab"}), - ("*b*", {"abcd", "abab", "bcde"}) - ]) -@pytest.mark.parametrize("skip,skip_set", [ - ("", set()), ("a*", {"aaaa", "abcd", "abab"}), - ("*c*", {"abcd", "bcde"}) -]) -def test_build_selector(system, build, build_set, skip, skip_set, monkeypatch, argtest): - monkeypatch.setattr(globals()[system], "build", argtest) - env = {"CIBW_PLATFORM": system, "CIBW_BUILD": build, "CIBW_SKIP": skip} - monkeypatch.setattr(os, 'environ', env) - main() - assert isinstance(argtest.kwargs["build_selector"], BuildSelector) - selector = argtest.kwargs["build_selector"] - selected = set([x for x in ["aaaa", "abcd", "abab", "bcde"] if selector(x)]) - assert selected == build_set.difference(skip_set) - - -@pytest.mark.parametrize("system", ["macos", "windows"]) -@pytest.mark.parametrize("manylinux", ["none", "manylinux1"]) -def test_no_manylinux(system, manylinux, monkeypatch, argtest): - monkeypatch.setattr(globals()[system], "build", argtest) - env = {"CIBW_PLATFORM": system} - if manylinux != "none": - env["CIBW_MANYLINUX_I686_IMAGE"] = manylinux - env["CIBW_MANYLINUX_X86_64_IMAGE"] = manylinux - monkeypatch.setattr(os, 'environ', env) - main() - assert "manylinux_images" not in argtest.kwargs - - -@pytest.mark.parametrize("manylinux86,manylinux86_image", [ - ("none", 'quay.io/pypa/manylinux2010_i686'), - ("manylinux1", 'quay.io/pypa/manylinux1_i686'), - ("manylinux2010", 'quay.io/pypa/manylinux2010_i686'), - ("asfsgd", "asfsgd")]) -@pytest.mark.parametrize("manylinux64, manylinux64_image", [ - ("none", 'quay.io/pypa/manylinux2010_x86_64'), - ("manylinux1", 'quay.io/pypa/manylinux1_x86_64'), - ("manylinux2010", 'quay.io/pypa/manylinux2010_x86_64'), - ("asfsgd", "asfsgd")]) -def test_manylinux_choose(manylinux86, manylinux86_image, manylinux64, - manylinux64_image, monkeypatch, argtest): - monkeypatch.setattr(linux, "build", argtest) - env = {"CIBW_PLATFORM": "linux"} - if manylinux86 != "none": - env["CIBW_MANYLINUX_I686_IMAGE"] = manylinux86 - if manylinux64 != "none": - env["CIBW_MANYLINUX_X86_64_IMAGE"] = manylinux64 - monkeypatch.setattr(os, 'environ', env) - main() - assert argtest.kwargs["manylinux_images"]['x86_64'] == manylinux64_image - assert argtest.kwargs["manylinux_images"]['i686'] == manylinux86_image - - -@pytest.mark.parametrize("system,default_repair", [ - ("macos", "delocate"), ("linux", "auditwheel"), - ("windows", "")]) -@pytest.mark.parametrize("repair_command", ["none", "aaaa", "repair -w {dest_dir} {wheel}"]) -@pytest.mark.parametrize("system_suffix", (True, False)) -def test_repair_command(system, default_repair, repair_command, system_suffix, monkeypatch, argtest): - monkeypatch.setattr(globals()[system], "build", argtest) - env = {"CIBW_PLATFORM": system} - if repair_command != "none": - env["CIBW_REPAIR_WHEEL_COMMAND"] = repair_command - if system_suffix: - env["CIBW_REPAIR_WHEEL_COMMAND_" + system.upper()] = "abcabc" - monkeypatch.setattr(os, 'environ', env) - main() - if system_suffix: - assert argtest.kwargs["repair_command"] == "abcabc" - elif repair_command == "none": - if default_repair: - assert argtest.kwargs["repair_command"].startswith(default_repair) - else: - assert len(argtest.kwargs["repair_command"]) == 0 - else: - assert argtest.kwargs["repair_command"] == repair_command - -@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) -@pytest.mark.parametrize("environment", [{}, {"AAA": "123"}, {"AA1": "124", "AA2": "124"}]) -@pytest.mark.parametrize("platform_environment", [{}, {"BBB": "123"}, {"BB1": "123", "BB2": "127"}]) -def test_environment(system, environment, platform_environment, monkeypatch, argtest): - monkeypatch.setattr(globals()[system], "build", argtest) - env = {"CIBW_PLATFORM": system} - cibw_env = " ".join(["{}={}".format(k, v) for k, v in environment.items()]) - platform_env = " ".join(["{}={}".format(k, v) for k, v in platform_environment.items()]) - if cibw_env: - env["CIBW_ENVIRONMENT"] = cibw_env - if platform_env: - env["CIBW_ENVIRONMENT_{}".format(system.upper())] = platform_env - monkeypatch.setattr(os, 'environ', env) - main() - assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) - if platform_environment: - assert argtest.kwargs["environment"].as_dictionary({}) == platform_environment - else: - assert argtest.kwargs["environment"].as_dictionary({}) == environment - - -@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) -@pytest.mark.parametrize("test_requires", ["", "test1"]) -@pytest.mark.parametrize("platform_test_requires", ["", "test2"]) -def test_test_requires(system, test_requires, platform_test_requires, monkeypatch, argtest): - monkeypatch.setattr(globals()[system], "build", argtest) - env = {"CIBW_PLATFORM": system} - if test_requires: - env["CIBW_TEST_REQUIRES"] = test_requires - if platform_test_requires: - env["CIBW_TEST_REQUIRES_{}".format(system.upper())] = platform_test_requires - monkeypatch.setattr(os, 'environ', env) - main() - assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) - if platform_test_requires: - assert argtest.kwargs["test_requires"] == platform_test_requires.split() - else: - assert argtest.kwargs["test_requires"] == test_requires.split() - - -@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) -@pytest.mark.parametrize("test_extras", ["", "test1"]) -@pytest.mark.parametrize("platform_test_extras", ["", "test2"]) -def test_test_extras(system, test_extras, platform_test_extras, monkeypatch, argtest): - monkeypatch.setattr(globals()[system], "build", argtest) - env = {"CIBW_PLATFORM": system} - if test_extras: - env["CIBW_TEST_EXTRAS"] = test_extras - if platform_test_extras: - env["CIBW_TEST_EXTRAS_{}".format(system.upper())] = platform_test_extras - monkeypatch.setattr(os, 'environ', env) - main() - assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) - if platform_test_extras: - assert argtest.kwargs["test_extras"] == "[" + platform_test_extras + "]" - elif test_extras: - assert argtest.kwargs["test_extras"] == "[" + test_extras + "]" - else: - assert argtest.kwargs["test_extras"] == "" - - -@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) -@pytest.mark.parametrize("test_command", [None, "test1"]) -@pytest.mark.parametrize("platform_test_command", [None, "test2"]) -def test_test_command(system, test_command, platform_test_command, monkeypatch, argtest): - monkeypatch.setattr(globals()[system], "build", argtest) - env = {"CIBW_PLATFORM": system} - if test_command: - env["CIBW_TEST_COMMAND"] = test_command - if platform_test_command: - env["CIBW_TEST_COMMAND_{}".format(system.upper())] = platform_test_command - monkeypatch.setattr(os, 'environ', env) - main() - assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) - if platform_test_command: - assert argtest.kwargs["test_command"] == platform_test_command - else: - assert argtest.kwargs["test_command"] == test_command - - -@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) -@pytest.mark.parametrize("before_build", [None, "test1"]) -@pytest.mark.parametrize("platform_before_build", [None, "test2"]) -def test_before_build(system, before_build, platform_before_build, monkeypatch, argtest): - monkeypatch.setattr(globals()[system], "build", argtest) - env = {"CIBW_PLATFORM": system} - if before_build: - env["CIBW_BEFORE_BUILD"] = before_build - if platform_before_build: - env["CIBW_BEFORE_BUILD_{}".format(system.upper())] = platform_before_build - monkeypatch.setattr(os, 'environ', env) - main() - assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) - if platform_before_build: - assert argtest.kwargs["before_build"] == platform_before_build - else: - assert argtest.kwargs["before_build"] == before_build - - -@pytest.mark.parametrize("system", ["macos", "linux", "windows"]) -@pytest.mark.parametrize("verbosity", [None, 0, -2, 4]) -@pytest.mark.parametrize("platform_verbosity", [None, 0, 2, -4]) -def test_build_verbosity(system, verbosity, platform_verbosity, monkeypatch, argtest): - monkeypatch.setattr(globals()[system], "build", argtest) - env = {"CIBW_PLATFORM": system} - if verbosity is not None: - env["CIBW_BUILD_VERBOSITY"] = verbosity - if platform_verbosity is not None: - env["CIBW_BUILD_VERBOSITY_{}".format(system.upper())] = platform_verbosity - monkeypatch.setattr(os, 'environ', env) - main() - assert isinstance(argtest.kwargs["environment"], ParsedEnvironment) - if platform_verbosity is not None: - assert argtest.kwargs["build_verbosity"] == platform_verbosity if platform_verbosity > -4 else -3 - elif verbosity is not None: - assert argtest.kwargs["build_verbosity"] == verbosity if verbosity < 4 else 3 - else: - assert argtest.kwargs["build_verbosity"] == 0 \ No newline at end of file diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py new file mode 100644 index 00000000..ef7211ba --- /dev/null +++ b/unit_test/main_options_test.py @@ -0,0 +1,203 @@ +import pytest + +import sys + +from cibuildwheel import linux, macos, windows +from cibuildwheel.__main__ import main +from cibuildwheel.environment import ParsedEnvironment +from cibuildwheel.util import BuildSelector + +from main_util_fixtures import mock_protection, platform, intercepted_build_args + + + +# CIBW_PLATFORM is tested in main_platform_test.py + + +def test_output_dir(platform, intercepted_build_args, monkeypatch): + OUTPUT_DIR = 'some_output_dir' + + monkeypatch.setenv('CIBW_OUTPUT_DIR', OUTPUT_DIR) + + main() + + assert intercepted_build_args.kwargs['output_dir'] == OUTPUT_DIR + + +def test_output_dir_default(platform, intercepted_build_args, monkeypatch): + main() + + assert intercepted_build_args.kwargs['output_dir'] == 'wheelhouse' + + +@pytest.mark.parametrize('also_set_environment', [False, True]) +def test_output_dir_argument(also_set_environment, platform, intercepted_build_args, monkeypatch): + OUTPUT_DIR = 'some_output_dir' + + monkeypatch.setattr(sys, 'argv', sys.argv + ['--output-dir', OUTPUT_DIR]) + if also_set_environment: + monkeypatch.setenv('CIBW_OUTPUT_DIR', 'not_this_output_dir') + + main() + + assert intercepted_build_args.kwargs['output_dir'] == OUTPUT_DIR + + +def test_build_selector(platform, intercepted_build_args, monkeypatch): + BUILD = 'some build* *-selector' + SKIP = 'some skip* *-selector' + + monkeypatch.setenv('CIBW_BUILD', BUILD) + monkeypatch.setenv('CIBW_SKIP', SKIP) + + main() + + intercepted_build_selector = intercepted_build_args.kwargs['build_selector'] + assert isinstance(intercepted_build_selector, BuildSelector) + assert intercepted_build_selector('build-this') + assert not intercepted_build_selector('skip-that') + # This unit test is just testing the options of 'main' + # Unit tests for BuildSelector are in build_selector_test.py + + +@pytest.mark.parametrize('architecture, image, full_image', [ + ('x86_64', None, 'quay.io/pypa/manylinux2010_x86_64'), + ('x86_64', 'manylinux1', 'quay.io/pypa/manylinux1_x86_64'), + ('x86_64', 'manylinux2010', 'quay.io/pypa/manylinux2010_x86_64'), + ('x86_64', 'custom_image', None), + ('i686', None, 'quay.io/pypa/manylinux2010_i686'), + ('i686', 'manylinux1', 'quay.io/pypa/manylinux1_i686'), + ('i686', 'manylinux2010', 'quay.io/pypa/manylinux2010_i686'), + ('i686', 'custom_image', None), +]) +def test_manylinux_images(architecture, image, full_image, platform, intercepted_build_args, monkeypatch): + if image is not None: + monkeypatch.setenv('CIBW_MANYLINUX_' + architecture.upper() + '_IMAGE', image) + + main() + + if platform == 'linux': + assert intercepted_build_args.kwargs['manylinux_images'][architecture] == full_image or image + else: + assert 'manylinux_images' not in intercepted_build_args.kwargs + + +def get_default_repair_command(platform): + if platform == 'linux': + return 'auditwheel repair -w {dest_dir} {wheel}' + elif platform == 'macos': + return 'delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} {wheel}' + elif platform == 'windows': + return '' + +@pytest.mark.parametrize('repair_command', [None, 'repair', 'repair -w {dest_dir} {wheel}']) +@pytest.mark.parametrize('platform_specific', [False, True]) +def test_repair_command(repair_command, platform_specific, platform, intercepted_build_args, monkeypatch): + if repair_command is not None: + if platform_specific: + monkeypatch.setenv('CIBW_REPAIR_WHEEL_COMMAND_' + platform.upper(), repair_command) + monkeypatch.setenv('CIBW_REPAIR_WHEEL_COMMAND', 'overwritten') + else: + monkeypatch.setenv('CIBW_REPAIR_WHEEL_COMMAND', repair_command) + + main() + + expected_repair = repair_command or get_default_repair_command(platform) + assert intercepted_build_args.kwargs['repair_command'] == expected_repair + + +@pytest.mark.parametrize('environment', [ + {}, + {'something': 'value'}, + {'something': 'value', 'something_else': 'other_value'} +]) +@pytest.mark.parametrize('platform_specific', [False, True]) +def test_environment(environment, platform_specific, platform, intercepted_build_args, monkeypatch): + env_string = ' '.join(['{}={}'.format(k, v) for k, v in environment.items()]) + if platform_specific: + monkeypatch.setenv('CIBW_ENVIRONMENT_' + platform.upper(), env_string) + monkeypatch.setenv('CIBW_ENVIRONMENT', 'overwritten') + else: + monkeypatch.setenv('CIBW_ENVIRONMENT', env_string) + + main() + + intercepted_environment = intercepted_build_args.kwargs['environment'] + assert isinstance(intercepted_environment, ParsedEnvironment) + assert intercepted_environment.as_dictionary({}) == environment + + +@pytest.mark.parametrize('test_requires', [None, 'requirement other_requirement']) +@pytest.mark.parametrize('platform_specific', [False, True]) +def test_test_requires(test_requires, platform_specific, platform, intercepted_build_args, monkeypatch): + if test_requires is not None: + if platform_specific: + monkeypatch.setenv('CIBW_TEST_REQUIRES_' + platform.upper(), test_requires) + monkeypatch.setenv('CIBW_TEST_REQUIRES', 'overwritten') + else: + monkeypatch.setenv('CIBW_TEST_REQUIRES', test_requires) + + main() + + assert intercepted_build_args.kwargs['test_requires'] == (test_requires or '').split() + + +@pytest.mark.parametrize('test_extras', [None, 'extras']) +@pytest.mark.parametrize('platform_specific', [False, True]) +def test_test_extras(test_extras, platform_specific, platform, intercepted_build_args, monkeypatch): + if test_extras is not None: + if platform_specific: + monkeypatch.setenv('CIBW_TEST_EXTRAS_' + platform.upper(), test_extras) + monkeypatch.setenv('CIBW_TEST_EXTRAS', 'overwritten') + else: + monkeypatch.setenv('CIBW_TEST_EXTRAS', test_extras) + + main() + + assert intercepted_build_args.kwargs['test_extras'] == ('[' + test_extras + ']' if test_extras else '') + + +@pytest.mark.parametrize('test_command', [None, 'test --command']) +@pytest.mark.parametrize('platform_specific', [False, True]) +def test_test_command(test_command, platform_specific, platform, intercepted_build_args, monkeypatch): + if test_command is not None: + if platform_specific: + monkeypatch.setenv('CIBW_TEST_COMMAND_' + platform.upper(), test_command) + monkeypatch.setenv('CIBW_TEST_COMMAND', 'overwritten') + else: + monkeypatch.setenv('CIBW_TEST_COMMAND', test_command) + + main() + + assert intercepted_build_args.kwargs['test_command'] == test_command or '' + + +@pytest.mark.parametrize('before_build', [None, 'before --build']) +@pytest.mark.parametrize('platform_specific', [False, True]) +def test_before_build(before_build, platform_specific, platform, intercepted_build_args, monkeypatch): + if before_build is not None: + if platform_specific: + monkeypatch.setenv('CIBW_BEFORE_BUILD_' + platform.upper(), before_build) + monkeypatch.setenv('CIBW_BEFORE_BUILD', 'overwritten') + else: + monkeypatch.setenv('CIBW_BEFORE_BUILD', before_build) + + main() + + assert intercepted_build_args.kwargs['before_build'] == before_build or '' + + +@pytest.mark.parametrize('build_verbosity', [None, 0, 2, -2, 4, -4]) +@pytest.mark.parametrize('platform_specific', [False, True]) +def test_build_verbosity(build_verbosity, platform_specific, platform, intercepted_build_args, monkeypatch): + if build_verbosity is not None: + if platform_specific: + monkeypatch.setenv('CIBW_BUILD_VERBOSITY_' + platform.upper(), str(build_verbosity)) + monkeypatch.setenv('CIBW_BUILD_VERBOSITY', 'overwritten') + else: + monkeypatch.setenv('CIBW_BUILD_VERBOSITY', str(build_verbosity)) + + main() + + expected_verbosity = max(-3, min(3, int(build_verbosity or 0))) + assert intercepted_build_args.kwargs['build_verbosity'] == expected_verbosity diff --git a/unit_test/main_platform_test.py b/unit_test/main_platform_test.py new file mode 100644 index 00000000..1d9f0cff --- /dev/null +++ b/unit_test/main_platform_test.py @@ -0,0 +1,59 @@ +import pytest + +import sys + +from cibuildwheel.__main__ import main +from cibuildwheel import linux, macos, windows + +from main_util_fixtures import MOCK_PROJECT_DIR, mock_protection, platform, intercepted_build_args + + +def test_unknown_platform_non_ci(monkeypatch, capsys): + monkeypatch.delenv('CI', raising=False) + monkeypatch.delenv('BITRISE_BUILD_NUMBER', raising=False) + monkeypatch.delenv('AZURE_HTTP_USER_AGENT', raising=False) + + with pytest.raises(SystemExit) as exit: + main() + assert exit.value.code == 2 + _, err = capsys.readouterr() + + assert 'cibuildwheel: Unable to detect platform.' in err + assert 'cibuildwheel should run on your CI server' in err + + +def test_unknown_platform_on_ci(monkeypatch, capsys): + monkeypatch.setenv('CI', 'true') + monkeypatch.setattr(sys, 'platform', 'nonexistent') + + with pytest.raises(SystemExit) as exit: + main() + assert exit.value.code == 2 + _, err = capsys.readouterr() + + assert 'cibuildwheel: Unable to detect platform from "sys.platform"' in err + + +def test_unknown_platform(monkeypatch, capsys): + monkeypatch.setenv('CIBW_PLATFORM', 'nonexistent') + + with pytest.raises(SystemExit) as exit: + main() + _, err = capsys.readouterr() + + assert exit.value.code == 2 + assert 'cibuildwheel: Unsupported platform: nonexistent' in err + + +def test_platform_argument(platform, intercepted_build_args, monkeypatch): + monkeypatch.setattr(sys, 'argv', sys.argv + ['--platform', platform]) + + main() + + assert intercepted_build_args.kwargs['project_dir'] == MOCK_PROJECT_DIR + + +def test_platform_environment(platform, intercepted_build_args, monkeypatch): + main() + + assert intercepted_build_args.kwargs['project_dir'] == MOCK_PROJECT_DIR diff --git a/unit_test/main_util_fixtures.py b/unit_test/main_util_fixtures.py new file mode 100644 index 00000000..ae7bd006 --- /dev/null +++ b/unit_test/main_util_fixtures.py @@ -0,0 +1,43 @@ +import pytest + +import sys +import os +import subprocess + +from cibuildwheel import linux, macos, windows + + +class ArgsInterceptor(object): + def __call__(self, *args, **kwargs): + self.args = args + self.kwargs = kwargs + + +MOCK_PROJECT_DIR = 'some_project_dir' + +@pytest.fixture(autouse=True) +def mock_protection(monkeypatch): + def fail_on_call(*args, **kwargs): + raise RuntimeError("This should never be called") + + monkeypatch.setattr(subprocess, 'Popen', fail_on_call) + monkeypatch.setattr(windows, 'urlopen', fail_on_call) + monkeypatch.setattr(windows, 'build', fail_on_call) + monkeypatch.setattr(linux, 'build', fail_on_call) + monkeypatch.setattr(macos, 'build', fail_on_call) + monkeypatch.setattr(os.path, 'exists', lambda x: True) + monkeypatch.setattr(sys, 'argv', ['cibuildwheel', MOCK_PROJECT_DIR]) + + +@pytest.fixture(params=['linux', 'macos', 'windows']) +def platform(request, monkeypatch): + platform_value = request.param + monkeypatch.setenv('CIBW_PLATFORM', platform_value) + return platform_value + + +@pytest.fixture +def intercepted_build_args(platform, monkeypatch): + intercepted = ArgsInterceptor() + monkeypatch.setattr(globals()[platform], 'build', intercepted) + return intercepted From a9c968868a0f557dfa4ad73cc571a65448825fa1 Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Mon, 16 Dec 2019 11:32:09 +0100 Subject: [PATCH 5/9] Fix main_platform_test.py::test_platform_argument, making sure --platform overrides CIBW_PLATFORM --- unit_test/main_platform_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/unit_test/main_platform_test.py b/unit_test/main_platform_test.py index 1d9f0cff..a41727b5 100644 --- a/unit_test/main_platform_test.py +++ b/unit_test/main_platform_test.py @@ -46,6 +46,7 @@ def test_unknown_platform(monkeypatch, capsys): def test_platform_argument(platform, intercepted_build_args, monkeypatch): + monkeypatch.setenv('CIBW_PLATFORM', 'nonexistent') monkeypatch.setattr(sys, 'argv', sys.argv + ['--platform', platform]) main() From de55153931374d6e832fecbacc22c820b84f4ef5 Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Mon, 16 Dec 2019 23:39:18 +0100 Subject: [PATCH 6/9] Remove 'from cibuildwheel import linux, macos, windows' from new tests, as imports are done in fixtures --- unit_test/main_options_test.py | 1 - unit_test/main_platform_test.py | 1 - 2 files changed, 2 deletions(-) diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py index ef7211ba..a4440210 100644 --- a/unit_test/main_options_test.py +++ b/unit_test/main_options_test.py @@ -2,7 +2,6 @@ import pytest import sys -from cibuildwheel import linux, macos, windows from cibuildwheel.__main__ import main from cibuildwheel.environment import ParsedEnvironment from cibuildwheel.util import BuildSelector diff --git a/unit_test/main_platform_test.py b/unit_test/main_platform_test.py index a41727b5..101d3c4f 100644 --- a/unit_test/main_platform_test.py +++ b/unit_test/main_platform_test.py @@ -3,7 +3,6 @@ import pytest import sys from cibuildwheel.__main__ import main -from cibuildwheel import linux, macos, windows from main_util_fixtures import MOCK_PROJECT_DIR, mock_protection, platform, intercepted_build_args From 8bfe9ac6cd92a1136ffc077d652e7265f58e2e35 Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Thu, 26 Dec 2019 14:41:24 +0100 Subject: [PATCH 7/9] Fix @joerick's remarks in unit_test/main_options_test.py --- unit_test/main_options_test.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py index a4440210..cebcdbbb 100644 --- a/unit_test/main_options_test.py +++ b/unit_test/main_options_test.py @@ -63,11 +63,11 @@ def test_build_selector(platform, intercepted_build_args, monkeypatch): ('x86_64', None, 'quay.io/pypa/manylinux2010_x86_64'), ('x86_64', 'manylinux1', 'quay.io/pypa/manylinux1_x86_64'), ('x86_64', 'manylinux2010', 'quay.io/pypa/manylinux2010_x86_64'), - ('x86_64', 'custom_image', None), + ('x86_64', 'custom_image', 'custom_image'), ('i686', None, 'quay.io/pypa/manylinux2010_i686'), ('i686', 'manylinux1', 'quay.io/pypa/manylinux1_i686'), ('i686', 'manylinux2010', 'quay.io/pypa/manylinux2010_i686'), - ('i686', 'custom_image', None), + ('i686', 'custom_image', 'custom_image'), ]) def test_manylinux_images(architecture, image, full_image, platform, intercepted_build_args, monkeypatch): if image is not None: @@ -76,7 +76,7 @@ def test_manylinux_images(architecture, image, full_image, platform, intercepted main() if platform == 'linux': - assert intercepted_build_args.kwargs['manylinux_images'][architecture] == full_image or image + assert intercepted_build_args.kwargs['manylinux_images'][architecture] == full_image else: assert 'manylinux_images' not in intercepted_build_args.kwargs @@ -88,6 +88,8 @@ def get_default_repair_command(platform): return 'delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} {wheel}' elif platform == 'windows': return '' + else: + raise ValueError('Unknown platform', platform) @pytest.mark.parametrize('repair_command', [None, 'repair', 'repair -w {dest_dir} {wheel}']) @pytest.mark.parametrize('platform_specific', [False, True]) @@ -123,7 +125,7 @@ def test_environment(environment, platform_specific, platform, intercepted_build intercepted_environment = intercepted_build_args.kwargs['environment'] assert isinstance(intercepted_environment, ParsedEnvironment) - assert intercepted_environment.as_dictionary({}) == environment + assert intercepted_environment.as_dictionary(prev_environment={}) == environment @pytest.mark.parametrize('test_requires', [None, 'requirement other_requirement']) @@ -168,7 +170,7 @@ def test_test_command(test_command, platform_specific, platform, intercepted_bui main() - assert intercepted_build_args.kwargs['test_command'] == test_command or '' + assert intercepted_build_args.kwargs['test_command'] == test_command @pytest.mark.parametrize('before_build', [None, 'before --build']) @@ -183,7 +185,7 @@ def test_before_build(before_build, platform_specific, platform, intercepted_bui main() - assert intercepted_build_args.kwargs['before_build'] == before_build or '' + assert intercepted_build_args.kwargs['before_build'] == before_build @pytest.mark.parametrize('build_verbosity', [None, 0, 2, -2, 4, -4]) From fabb82e9cf221775642131d60d7bb1ec353b84dd Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Thu, 26 Dec 2019 15:03:13 +0100 Subject: [PATCH 8/9] Add manylinux2014 to unit_test/main_options_test.py::test_manylinux_images --- unit_test/main_options_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py index cebcdbbb..1914f550 100644 --- a/unit_test/main_options_test.py +++ b/unit_test/main_options_test.py @@ -63,10 +63,12 @@ def test_build_selector(platform, intercepted_build_args, monkeypatch): ('x86_64', None, 'quay.io/pypa/manylinux2010_x86_64'), ('x86_64', 'manylinux1', 'quay.io/pypa/manylinux1_x86_64'), ('x86_64', 'manylinux2010', 'quay.io/pypa/manylinux2010_x86_64'), + ('x86_64', 'manylinux2014', 'quay.io/pypa/manylinux2014_x86_64'), ('x86_64', 'custom_image', 'custom_image'), ('i686', None, 'quay.io/pypa/manylinux2010_i686'), ('i686', 'manylinux1', 'quay.io/pypa/manylinux1_i686'), ('i686', 'manylinux2010', 'quay.io/pypa/manylinux2010_i686'), + ('i686', 'manylinux2014', 'quay.io/pypa/manylinux2014_i686'), ('i686', 'custom_image', 'custom_image'), ]) def test_manylinux_images(architecture, image, full_image, platform, intercepted_build_args, monkeypatch): From 492b5f4039d3298ece0d131503dcce44a2010347 Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Fri, 27 Dec 2019 00:56:00 +0100 Subject: [PATCH 9/9] Splitting off fake_project_dir fixture from mock_protection, only mocking os.path.exist for setup.py in the mocked project directory --- unit_test/main_options_test.py | 2 +- unit_test/main_platform_test.py | 2 +- unit_test/main_util_fixtures.py | 21 ++++++++++++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py index 1914f550..90935fe8 100644 --- a/unit_test/main_options_test.py +++ b/unit_test/main_options_test.py @@ -6,7 +6,7 @@ from cibuildwheel.__main__ import main from cibuildwheel.environment import ParsedEnvironment from cibuildwheel.util import BuildSelector -from main_util_fixtures import mock_protection, platform, intercepted_build_args +from main_util_fixtures import mock_protection, fake_project_dir, platform, intercepted_build_args diff --git a/unit_test/main_platform_test.py b/unit_test/main_platform_test.py index 101d3c4f..3de3be29 100644 --- a/unit_test/main_platform_test.py +++ b/unit_test/main_platform_test.py @@ -4,7 +4,7 @@ import sys from cibuildwheel.__main__ import main -from main_util_fixtures import MOCK_PROJECT_DIR, mock_protection, platform, intercepted_build_args +from main_util_fixtures import MOCK_PROJECT_DIR, mock_protection, fake_project_dir, platform, intercepted_build_args def test_unknown_platform_non_ci(monkeypatch, capsys): diff --git a/unit_test/main_util_fixtures.py b/unit_test/main_util_fixtures.py index ae7bd006..8bc80d87 100644 --- a/unit_test/main_util_fixtures.py +++ b/unit_test/main_util_fixtures.py @@ -17,6 +17,11 @@ MOCK_PROJECT_DIR = 'some_project_dir' @pytest.fixture(autouse=True) def mock_protection(monkeypatch): + ''' + Ensure that a unit test will never actually run a cibuildwheel 'build' + function, which shouldn't be run on a developer's machine + ''' + def fail_on_call(*args, **kwargs): raise RuntimeError("This should never be called") @@ -25,7 +30,21 @@ def mock_protection(monkeypatch): monkeypatch.setattr(windows, 'build', fail_on_call) monkeypatch.setattr(linux, 'build', fail_on_call) monkeypatch.setattr(macos, 'build', fail_on_call) - monkeypatch.setattr(os.path, 'exists', lambda x: True) + +@pytest.fixture(autouse=True) +def fake_project_dir(monkeypatch): + ''' + Monkey-patch enough for the main() function to run + ''' + + real_os_path_exists = os.path.exists + def mock_os_path_exists(path): + if path == os.path.join(MOCK_PROJECT_DIR, 'setup.py'): + return True + else: + return real_os_path_exists(path) + + monkeypatch.setattr(os.path, 'exists', mock_os_path_exists) monkeypatch.setattr(sys, 'argv', ['cibuildwheel', MOCK_PROJECT_DIR])