Add comprehensive tests for image processing nodes and refactor node imports
- Introduced new test files for image layer, image plane, normal scale, object normal rotation, shadeless, and temporary attributes. - Implemented tests to validate the behavior of alpha curves, depth layers, and normal scales in various rendering engines. - Refactored import paths for node groups to align with the new directory structure. - Added checks for temporary attribute lifetimes and ensured proper cleanup without warnings. - Enhanced CLI commands to require the Blender group and validate the presence of generated node assets before packaging. - Updated packaging scripts to enforce the existence of necessary assets, preventing build failures.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from tests.support.paths import PROJECT_ROOT
|
||||
import importlib.util
|
||||
import subprocess
|
||||
from unittest.mock import patch
|
||||
import pytest
|
||||
|
||||
@@ -17,84 +18,75 @@ def load_launcher():
|
||||
return module
|
||||
|
||||
|
||||
def test_blender_path_prefers_explicit_path(tmp_path):
|
||||
def test_commands_require_the_blender_group(monkeypatch):
|
||||
launcher = load_launcher()
|
||||
executable = tmp_path / "blender"
|
||||
executable.touch()
|
||||
|
||||
with patch.dict("os.environ", {"BLENDER_BIN": "ignored"}):
|
||||
assert launcher.blender_path(executable) == executable
|
||||
monkeypatch.setattr("sys.argv", ["node-group", "check"])
|
||||
with patch.object(launcher.importlib.util, "find_spec", return_value=None):
|
||||
with pytest.raises(RuntimeError, match="--group blender"):
|
||||
launcher.main()
|
||||
|
||||
|
||||
def test_blender_path_reads_environment(tmp_path):
|
||||
launcher = load_launcher()
|
||||
executable = tmp_path / "blender"
|
||||
executable.touch()
|
||||
|
||||
with patch.dict("os.environ", {"BLENDER_BIN": str(executable)}):
|
||||
assert launcher.blender_path() == executable
|
||||
|
||||
|
||||
def test_blender_path_reads_project_dotenv(tmp_path):
|
||||
launcher = load_launcher()
|
||||
executable = tmp_path / "Blender 4.5" / "blender.exe"
|
||||
executable.parent.mkdir()
|
||||
executable.touch()
|
||||
env_path = tmp_path / ".env"
|
||||
env_path.write_text(
|
||||
f'BLENDER_BIN="{executable}"\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
with patch.dict("os.environ", {}, clear=True), patch.object(
|
||||
launcher,
|
||||
"PROJECT_ROOT",
|
||||
tmp_path,
|
||||
):
|
||||
assert launcher.blender_path() == executable
|
||||
|
||||
|
||||
def test_blender_path_reports_missing_configuration(tmp_path):
|
||||
launcher = load_launcher()
|
||||
|
||||
with patch.dict("os.environ", {}, clear=True), patch.object(
|
||||
launcher.shutil,
|
||||
"which",
|
||||
return_value=None,
|
||||
), patch.object(
|
||||
launcher,
|
||||
"PROJECT_ROOT",
|
||||
tmp_path,
|
||||
):
|
||||
with pytest.raises(RuntimeError, match="Blender not found"):
|
||||
launcher.blender_path()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("arguments,modules,run_tests", [
|
||||
(["build"], ("tools.nodes.build", "tools.nodes.check"), True),
|
||||
(["check", "--skip-tests"], ("tools.nodes.check",), False),
|
||||
(["preview", "--fragment"], ("tools.nodes.preview.export",), False),
|
||||
@pytest.mark.parametrize("arguments,commands", [
|
||||
(["build"], [
|
||||
("tools.nodes.build", ()),
|
||||
("tools.nodes.check", ()),
|
||||
("pytest", ("tests/nodes", "tests/tools/nodes")),
|
||||
]),
|
||||
(["check", "--skip-tests"], [("tools.nodes.check", ())]),
|
||||
(["preview", "--fragment"], [
|
||||
("tools.nodes.preview.export", "preview"),
|
||||
]),
|
||||
])
|
||||
def test_commands_dispatch_requested_work(monkeypatch, tmp_path, arguments, modules, run_tests):
|
||||
def test_commands_dispatch_requested_work(monkeypatch, tmp_path, arguments, commands):
|
||||
launcher = load_launcher()
|
||||
output = tmp_path / "node groups.html"
|
||||
command = ["node-group", *arguments]
|
||||
if arguments[0] == "preview":
|
||||
command += ["--output", str(output)]
|
||||
monkeypatch.setattr("sys.argv", command)
|
||||
monkeypatch.setattr(launcher, "blender_path", lambda _: "blender")
|
||||
with (
|
||||
patch.object(launcher, "run_blender_modules") as blender,
|
||||
patch.object(launcher, "require_bpy"),
|
||||
patch.object(launcher, "run_module") as run_module,
|
||||
patch.object(launcher, "run") as run,
|
||||
patch.object(launcher.webbrowser, "open") as open_browser,
|
||||
):
|
||||
launcher.main()
|
||||
if arguments[0] == "preview":
|
||||
blender.assert_called_once_with("blender", modules, ["--output", str(output), "--fragment"])
|
||||
run_module.assert_called_once_with(
|
||||
"tools.nodes.preview.export",
|
||||
["--output", str(output), "--fragment"],
|
||||
)
|
||||
open_browser.assert_not_called()
|
||||
else:
|
||||
blender.assert_called_once_with("blender", modules)
|
||||
if run_tests:
|
||||
run.assert_called_once_with((launcher.sys.executable, "-m", "pytest"))
|
||||
expected_modules = [item[0] for item in commands if item[0] != "pytest"]
|
||||
assert [call.args[0] for call in run_module.call_args_list] == expected_modules
|
||||
if any(item[0] == "pytest" for item in commands):
|
||||
run.assert_called_once_with(
|
||||
(
|
||||
launcher.sys.executable,
|
||||
"-m",
|
||||
"pytest",
|
||||
"tests/nodes",
|
||||
"tests/tools/nodes",
|
||||
)
|
||||
)
|
||||
else:
|
||||
run.assert_not_called()
|
||||
|
||||
|
||||
def test_module_failure_stops_later_steps(monkeypatch):
|
||||
launcher = load_launcher()
|
||||
monkeypatch.setattr("sys.argv", ["node-group", "build"])
|
||||
with (
|
||||
patch.object(launcher, "require_bpy"),
|
||||
patch.object(
|
||||
launcher,
|
||||
"run_module",
|
||||
side_effect=subprocess.CalledProcessError(1, "build"),
|
||||
) as run_module,
|
||||
patch.object(launcher, "run") as run,
|
||||
):
|
||||
with pytest.raises(subprocess.CalledProcessError):
|
||||
launcher.main()
|
||||
run_module.assert_called_once_with("tools.nodes.build")
|
||||
run.assert_not_called()
|
||||
|
||||
Reference in New Issue
Block a user