From 69309da827b0cef307cb72184c5cd8b4aafdb82d Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Tue, 3 Feb 2026 04:18:37 +0000 Subject: [PATCH] Add tests, fixtures, and CI/CD workflow --- tests/test_dataforge_commands.py | 185 +++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 tests/test_dataforge_commands.py diff --git a/tests/test_dataforge_commands.py b/tests/test_dataforge_commands.py new file mode 100644 index 0000000..40253f8 --- /dev/null +++ b/tests/test_dataforge_commands.py @@ -0,0 +1,185 @@ +"""Tests for CLI commands.""" + +import json +import os +import tempfile + +import pytest +from click.testing import CliRunner + +from dataforge.cli import main +from dataforge.commands import convert, validate, batch_validate, typecheck + + +FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "dataforge_fixtures") + + +class TestConvertCommand: + """Tests for convert command.""" + + def test_convert_json_to_yaml(self): + runner = CliRunner() + input_file = os.path.join(FIXTURES_DIR, "sample.json") + with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: + output_file = f.name + try: + result = runner.invoke(convert, [input_file, output_file, "--to", "yaml"]) + assert result.exit_code == 0 + with open(output_file, "r") as f: + content = f.read() + assert "name:" in content + assert "test-project" in content + finally: + os.unlink(output_file) + + def test_convert_yaml_to_toml(self): + runner = CliRunner() + input_file = os.path.join(FIXTURES_DIR, "sample.yaml") + with tempfile.NamedTemporaryFile(mode="w", suffix=".toml", delete=False) as f: + output_file = f.name + try: + result = runner.invoke(convert, [input_file, output_file, "--to", "toml"]) + assert result.exit_code == 0 + with open(output_file, "r") as f: + content = f.read() + assert "name =" in content + finally: + os.unlink(output_file) + + def test_convert_with_explicit_format(self): + runner = CliRunner() + input_file = os.path.join(FIXTURES_DIR, "sample.json") + with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: + output_file = f.name + try: + result = runner.invoke(convert, [input_file, output_file, "--from", "json", "--to", "yaml"]) + assert result.exit_code == 0 + finally: + os.unlink(output_file) + + def test_convert_invalid_format(self): + runner = CliRunner() + input_file = os.path.join(FIXTURES_DIR, "sample.json") + with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f: + output_file = f.name + try: + result = runner.invoke(convert, [input_file, output_file, "--to", "invalid"]) + assert result.exit_code != 0 + finally: + os.unlink(output_file) + + def test_convert_compact_output(self): + runner = CliRunner() + input_file = os.path.join(FIXTURES_DIR, "sample.json") + with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: + output_file = f.name + try: + result = runner.invoke(convert, [input_file, output_file, "--to", "json", "--indent", "0"]) + assert result.exit_code == 0 + with open(output_file, "r") as f: + content = f.read() + assert "\n" not in content + finally: + os.unlink(output_file) + + +class TestValidateCommand: + """Tests for validate command.""" + + def test_validate_valid_file(self): + runner = CliRunner() + input_file = os.path.join(FIXTURES_DIR, "sample.json") + schema_file = os.path.join(FIXTURES_DIR, "valid_schema.json") + result = runner.invoke(validate, [input_file, "--schema", schema_file]) + assert result.exit_code == 0 + assert "passed" in result.output + + def test_validate_invalid_file(self): + runner = CliRunner() + schema_file = os.path.join(FIXTURES_DIR, "valid_schema.json") + with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: + json.dump({"name": "test", "version": "invalid"}, f) + invalid_file = f.name + try: + result = runner.invoke(validate, [invalid_file, "--schema", schema_file]) + assert result.exit_code != 0 + finally: + os.unlink(invalid_file) + + def test_validate_without_schema(self): + runner = CliRunner() + input_file = os.path.join(FIXTURES_DIR, "sample.json") + result = runner.invoke(validate, [input_file]) + assert result.exit_code == 0 + + def test_validate_quiet_mode(self): + runner = CliRunner() + input_file = os.path.join(FIXTURES_DIR, "sample.json") + schema_file = os.path.join(FIXTURES_DIR, "valid_schema.json") + result = runner.invoke(validate, [input_file, "--schema", schema_file, "--quiet"]) + assert result.exit_code == 0 + assert "passed" not in result.output + + +class TestBatchValidateCommand: + """Tests for batch validate command.""" + + def test_batch_validate_multiple_files(self): + runner = CliRunner() + schema_file = os.path.join(FIXTURES_DIR, "valid_schema.json") + input_files = [ + os.path.join(FIXTURES_DIR, "sample.json"), + os.path.join(FIXTURES_DIR, "sample.yaml"), + ] + result = runner.invoke(batch_validate, ["--schema", schema_file, *input_files]) + assert result.exit_code == 0 + assert "Valid" in result.output or "valid" in result.output + + def test_batch_validate_pattern(self): + runner = CliRunner() + schema_file = os.path.join(FIXTURES_DIR, "valid_schema.json") + json_file = os.path.join(FIXTURES_DIR, "sample.json") + result = runner.invoke(batch_validate, ["--schema", schema_file, json_file]) + assert result.exit_code == 0 + + +class TestTypeCheckCommand: + """Tests for typecheck command.""" + + def test_typecheck_simple_file(self): + runner = CliRunner() + input_file = os.path.join(FIXTURES_DIR, "sample.json") + result = runner.invoke(typecheck, [input_file]) + assert result.exit_code == 0 + assert "object" in result.output + + def test_typecheck_infer_schema(self): + runner = CliRunner() + input_file = os.path.join(FIXTURES_DIR, "sample.json") + result = runner.invoke(typecheck, [input_file, "--infer"]) + assert result.exit_code == 0 + assert '"type"' in result.output or "'type'" in result.output + + def test_typecheck_quiet_mode(self): + runner = CliRunner() + input_file = os.path.join(FIXTURES_DIR, "sample.json") + result = runner.invoke(typecheck, [input_file, "--quiet"]) + assert result.exit_code == 0 + + +class TestMainCLI: + """Tests for main CLI entry point.""" + + def test_main_help(self): + runner = CliRunner() + result = runner.invoke(main, ["--help"]) + assert result.exit_code == 0 + assert "DataForge" in result.output + assert "convert" in result.output + assert "validate" in result.output + + def test_main_version(self): + runner = CliRunner() + result = runner.invoke(main, ["--version"]) + assert result.exit_code == 0 + assert "1.0.0" in result.output