diff --git a/conda_build/build.py b/conda_build/build.py index 9e473facc9..6f11e14529 100644 --- a/conda_build/build.py +++ b/conda_build/build.py @@ -3483,6 +3483,19 @@ def test( if metadata.config.remove_work_dir: env["SRC_DIR"] = metadata.config.test_dir + for var in utils.ensure_list(metadata.get_value("test/script_env")): + if "=" in var: + val = var.split("=", 1)[1] + var = var.split("=", 1)[0] + env[var] = val + elif var not in os.environ: + warnings.warn( + f"The environment variable '{var}' specified in test/script_env is undefined.", + UserWarning, + ) + else: + env[var] = os.environ[var] + test_script, _ = write_test_scripts( metadata, env, py_files, pl_files, lua_files, r_files, shell_files, trace ) diff --git a/conda_build/metadata.py b/conda_build/metadata.py index 54961d0b47..379b68a3e7 100644 --- a/conda_build/metadata.py +++ b/conda_build/metadata.py @@ -727,6 +727,7 @@ def parse(data, config, path=None): "files": list, "imports": list, "source_files": list, + "script_env": list, "downstreams": list, }, "about": { diff --git a/docs/source/resources/define-metadata.rst b/docs/source/resources/define-metadata.rst index 1ccf6f201c..0461346b10 100644 --- a/docs/source/resources/define-metadata.rst +++ b/docs/source/resources/define-metadata.rst @@ -772,6 +772,8 @@ disable this with: include_recipe: False +.. _script-env: + Use environment variables ------------------------- @@ -1282,6 +1284,40 @@ Commands that are run as part of the test. - bspatch4 -h +.. _test-script-env: + +Test environment variables +--------------------------- + +Pass environment variables through to the test environment. +This works identically to :ref:`build/script_env `. + +.. code-block:: yaml + + test: + script_env: + - MYVAR + - ANOTHER_VAR + +If a listed environment variable is missing from the environment +seen by the conda-build process itself, a UserWarning is +emitted during the test phase and the variable remains +undefined. + +Values can also be set inline with ``=`` syntax: + +.. code-block:: yaml + + test: + script_env: + - MY_VAR=some value + +.. note:: + Environment variables inherited via ``test/script_env`` are only + visible during the test phase, not the build phase. Use + :ref:`build/script_env ` for build-time variables. + + Python imports -------------- diff --git a/docs/source/user-guide/environment-variables.rst b/docs/source/user-guide/environment-variables.rst index 1689b9106b..0e0a14d16a 100644 --- a/docs/source/user-guide/environment-variables.rst +++ b/docs/source/user-guide/environment-variables.rst @@ -327,6 +327,16 @@ Additionally, values can be set by including ``=`` followed by the desired value this feature with caution or explicitly set values using the ``=`` syntax. +This feature can also be used in the :ref:`test section ` of +``meta.yaml`` to pass environment variables to the test phase: + +.. code-block:: yaml + + test: + script_env: + - TMPDIR + - MY_VAR=some value + .. note:: If you split your build and test phases with ``--no-test`` and ``--test``, you need to ensure that the environment variables present at build time and test diff --git a/news/4940-test-script-env b/news/4940-test-script-env new file mode 100644 index 0000000000..36a35ed623 --- /dev/null +++ b/news/4940-test-script-env @@ -0,0 +1,7 @@ +### Enhancements + +* Allow setting environment variables in the test section via `test/script_env`, matching the existing `build/script_env` feature. (#4940) + +### Docs + +* Document `test/script_env` in the test section reference. diff --git a/tests/test_api_build.py b/tests/test_api_build.py index 5e002acfb2..5be113a0f0 100644 --- a/tests/test_api_build.py +++ b/tests/test_api_build.py @@ -2008,6 +2008,53 @@ def assert_keyword(keyword): os.environ.pop(token) +@pytest.mark.sanity +def test_test_script_env_warnings(testing_config, testing_workdir, recwarn): + os.makedirs("recipe") + with open("recipe/meta.yaml", "w") as f: + f.write(""" +package: + name: test-script-env-test + version: "1.0" + +build: + number: 0 + +test: + script_env: + - TEST_VAR + commands: + - echo "test" +""") + for empty in ("build.sh", "bld.bat"): + open(f"recipe/{empty}", "w").close() + + token = "TEST_VAR" + + def assert_undefined_warning_present(): + messages = [str(w.message) for w in recwarn.list] + assert any( + token in m and "test/script_env" in m and "undefined" in m for m in messages + ) + + def assert_undefined_warning_absent(): + messages = [str(w.message) for w in recwarn.list] + assert not any( + token in m and "test/script_env" in m and "undefined" in m for m in messages + ) + + api.build("recipe", config=testing_config) + assert_undefined_warning_present() + recwarn.clear() + + os.environ[token] = "value" + try: + api.build("recipe", config=testing_config) + assert_undefined_warning_absent() + finally: + os.environ.pop(token) + + @pytest.mark.slow def test_activated_prefixes_in_actual_path(testing_metadata): """