From a805c640ecffda6acef917788cda478f5c4d7973 Mon Sep 17 00:00:00 2001 From: Andrej Milicevic Date: Mon, 25 Aug 2025 16:21:02 +0200 Subject: [PATCH] Fix, remove, improve cli tests. --- .../integration/cli/test_cli_integration.py | 1 - cognee/tests/unit/cli/test_cli_edge_cases.py | 63 +++--- cognee/tests/unit/cli/test_cli_runner.py | 1 - cognee/tests/unit/cli/test_cli_utils.py | 194 +----------------- 4 files changed, 47 insertions(+), 212 deletions(-) diff --git a/cognee/tests/integration/cli/test_cli_integration.py b/cognee/tests/integration/cli/test_cli_integration.py index 8817f283a..af7f7983a 100644 --- a/cognee/tests/integration/cli/test_cli_integration.py +++ b/cognee/tests/integration/cli/test_cli_integration.py @@ -2,7 +2,6 @@ Integration tests for CLI commands that test end-to-end functionality. """ -import pytest import tempfile import os import sys diff --git a/cognee/tests/unit/cli/test_cli_edge_cases.py b/cognee/tests/unit/cli/test_cli_edge_cases.py index 0c60ad57e..81d30d65f 100644 --- a/cognee/tests/unit/cli/test_cli_edge_cases.py +++ b/cognee/tests/unit/cli/test_cli_edge_cases.py @@ -4,9 +4,7 @@ Tests for CLI edge cases and error scenarios with proper mocking. import pytest import argparse -import tempfile -import os -import asyncio +import types from unittest.mock import patch, MagicMock, AsyncMock from cognee.cli.commands.add_command import AddCommand from cognee.cli.commands.search_command import SearchCommand @@ -35,21 +33,8 @@ class TestAddCommandEdgeCases: command.execute(args) mock_asyncio_run.assert_called_once() - @patch("builtins.__import__") - @patch("cognee.cli.commands.add_command.asyncio.run") - def test_add_very_long_dataset_name(self, mock_asyncio_run, mock_import): - """Test add command with very long dataset name""" - # Mock the cognee module - mock_cognee = MagicMock() - mock_cognee.add = AsyncMock() - mock_import.return_value = mock_cognee - - command = AddCommand() - long_name = "a" * 1000 # Very long dataset name - args = argparse.Namespace(data=["test.txt"], dataset_name=long_name) - - command.execute(args) - mock_asyncio_run.assert_called_once() + coro = mock_asyncio_run.call_args[0][0] + assert isinstance(coro, types.CoroutineType) @patch("cognee.cli.commands.add_command.asyncio.run") def test_add_asyncio_run_exception(self, mock_asyncio_run): @@ -337,16 +322,37 @@ class TestCognifyCommandEdgeCases: command.execute(args) mock_asyncio_run.assert_called_once() - def test_cognify_empty_datasets_list(self): - """Test cognify command with empty datasets list""" + @patch("builtins.__import__") + @patch("cognee.cli.commands.cognify_command.asyncio.run") + def test_cognify_empty_datasets_list(self, mock_asyncio_run, mock_import): + """Test cognify command with nonexistent ontology file""" + # Mock the cognee module + mock_cognee = MagicMock() + mock_cognee.cognify = AsyncMock() + + def mock_import_func(name, fromlist=None, *args, **kwargs): + if name == "cognee": + return mock_cognee + elif name == "cognee.modules.chunking": + module = MagicMock() + module.TextChunker = MagicMock() + return module + return MagicMock() + + mock_import.side_effect = mock_import_func + command = CognifyCommand() - parser = argparse.ArgumentParser() - command.configure_parser(parser) - - # Empty datasets list should be handled - args = parser.parse_args(["--datasets"]) - assert args.datasets == [] + args = argparse.Namespace( + datasets=[], + chunk_size=None, + ontology_file=None, + chunker="TextChunker", + background=False, + verbose=False, + ) + command.execute(args) + mock_asyncio_run.assert_called_once() class TestDeleteCommandEdgeCases: """Test edge cases for DeleteCommand""" @@ -439,6 +445,7 @@ class TestConfigCommandEdgeCases: # Should handle the exception gracefully command.execute(args) + mock_cognee.config.get.assert_called_once_with("nonexistent_key") @patch("builtins.__import__") def test_config_set_complex_json_value(self, mock_import): @@ -450,9 +457,11 @@ class TestConfigCommandEdgeCases: command = ConfigCommand() complex_json = '{"nested": {"key": "value"}, "array": [1, 2, 3]}' + complex_json_expected_value = {"nested": {"key": "value"}, "array": [1, 2, 3]} args = argparse.Namespace(config_action="set", key="complex_config", value=complex_json) command.execute(args) + mock_cognee.config.set.assert_called_once_with("complex_config", complex_json_expected_value) @patch("builtins.__import__") def test_config_set_invalid_json_value(self, mock_import): @@ -467,6 +476,7 @@ class TestConfigCommandEdgeCases: args = argparse.Namespace(config_action="set", key="test_key", value=invalid_json) command.execute(args) + mock_cognee.config.set.assert_called_once_with("test_key", invalid_json) @patch("cognee.cli.commands.config_command.fmt.confirm") @patch("builtins.__import__") @@ -499,6 +509,7 @@ class TestConfigCommandEdgeCases: # Should handle AttributeError gracefully command.execute(args) + mock_cognee.config.unset.assert_not_called() def test_config_invalid_subcommand(self): """Test config command with invalid subcommand""" diff --git a/cognee/tests/unit/cli/test_cli_runner.py b/cognee/tests/unit/cli/test_cli_runner.py index bc0357abb..3f0ff2258 100644 --- a/cognee/tests/unit/cli/test_cli_runner.py +++ b/cognee/tests/unit/cli/test_cli_runner.py @@ -4,7 +4,6 @@ Test runner and utilities for CLI tests. import pytest import sys -import os from pathlib import Path diff --git a/cognee/tests/unit/cli/test_cli_utils.py b/cognee/tests/unit/cli/test_cli_utils.py index 318c04089..b38d4adbd 100644 --- a/cognee/tests/unit/cli/test_cli_utils.py +++ b/cognee/tests/unit/cli/test_cli_utils.py @@ -2,11 +2,6 @@ Tests for CLI utility functions and helper modules. """ -import pytest -from unittest.mock import patch, MagicMock -import click -from cognee.cli import echo as fmt -from cognee.cli.exceptions import CliCommandException, CliCommandInnerException from cognee.cli import debug from cognee.cli.config import ( CLI_DESCRIPTION, @@ -16,155 +11,7 @@ from cognee.cli.config import ( CHUNKER_CHOICES, OUTPUT_FORMAT_CHOICES, ) - - -class TestEchoModule: - """Test the CLI echo/formatting module""" - - @patch("click.secho") - def test_echo_basic(self, mock_secho): - """Test basic echo functionality""" - fmt.echo("test message") - mock_secho.assert_called_once_with("test message", fg=None, err=False) - - @patch("click.secho") - def test_echo_with_color(self, mock_secho): - """Test echo with color""" - fmt.echo("test message", color="red") - mock_secho.assert_called_once_with("test message", fg="red", err=False) - - @patch("click.secho") - def test_echo_to_stderr(self, mock_secho): - """Test echo to stderr""" - fmt.echo("test message", err=True) - mock_secho.assert_called_once_with("test message", fg=None, err=True) - - @patch("cognee.cli.echo.echo") - def test_note(self, mock_echo): - """Test note formatting""" - fmt.note("test note") - mock_echo.assert_called_once_with("Note: test note", color="blue") - - @patch("cognee.cli.echo.echo") - def test_warning(self, mock_echo): - """Test warning formatting""" - fmt.warning("test warning") - mock_echo.assert_called_once_with("Warning: test warning", color="yellow") - - @patch("cognee.cli.echo.echo") - def test_error(self, mock_echo): - """Test error formatting""" - fmt.error("test error") - mock_echo.assert_called_once_with("Error: test error", color="red", err=True) - - @patch("cognee.cli.echo.echo") - def test_success(self, mock_echo): - """Test success formatting""" - fmt.success("test success") - mock_echo.assert_called_once_with("Success: test success", color="green") - - @patch("click.style") - def test_bold(self, mock_style): - """Test bold text formatting""" - mock_style.return_value = "bold text" - result = fmt.bold("test text") - mock_style.assert_called_once_with("test text", bold=True) - assert result == "bold text" - - @patch("click.confirm") - def test_confirm(self, mock_confirm): - """Test confirmation prompt""" - mock_confirm.return_value = True - result = fmt.confirm("Are you sure?") - mock_confirm.assert_called_once_with("Are you sure?", default=False) - assert result is True - - @patch("click.confirm") - def test_confirm_with_default(self, mock_confirm): - """Test confirmation prompt with default""" - mock_confirm.return_value = False - result = fmt.confirm("Are you sure?", default=True) - mock_confirm.assert_called_once_with("Are you sure?", default=True) - assert result is False - - @patch("click.prompt") - def test_prompt(self, mock_prompt): - """Test user input prompt""" - mock_prompt.return_value = "user input" - result = fmt.prompt("Enter value:") - mock_prompt.assert_called_once_with("Enter value:", default=None) - assert result == "user input" - - @patch("click.prompt") - def test_prompt_with_default(self, mock_prompt): - """Test user input prompt with default""" - mock_prompt.return_value = "default value" - result = fmt.prompt("Enter value:", default="default value") - mock_prompt.assert_called_once_with("Enter value:", default="default value") - assert result == "default value" - - -class TestCliExceptions: - """Test CLI exception classes""" - - def test_cli_command_exception_basic(self): - """Test basic CliCommandException""" - exc = CliCommandException("Test error") - assert str(exc) == "Test error" - assert exc.error_code == -1 - assert exc.docs_url is None - assert exc.raiseable_exception is None - - def test_cli_command_exception_full(self): - """Test CliCommandException with all parameters""" - inner_exc = ValueError("Inner error") - exc = CliCommandException( - "Test error", - error_code=2, - docs_url="https://docs.test.com", - raiseable_exception=inner_exc, - ) - - assert str(exc) == "Test error" - assert exc.error_code == 2 - assert exc.docs_url == "https://docs.test.com" - assert exc.raiseable_exception is inner_exc - - def test_cli_command_inner_exception(self): - """Test CliCommandInnerException""" - exc = CliCommandInnerException("Inner error") - assert str(exc) == "Inner error" - assert isinstance(exc, Exception) - - -class TestDebugModule: - """Test CLI debug functionality""" - - def test_debug_initially_disabled(self): - """Test that debug is initially disabled""" - # Reset debug state - debug._debug_enabled = False - assert not debug.is_debug_enabled() - - def test_enable_debug(self): - """Test enabling debug mode""" - debug.enable_debug() - assert debug.is_debug_enabled() - - # Reset for other tests - debug._debug_enabled = False - - def test_debug_state_persistence(self): - """Test that debug state persists""" - debug.enable_debug() - assert debug.is_debug_enabled() - - # Should still be enabled - assert debug.is_debug_enabled() - - # Reset for other tests - debug._debug_enabled = False - +from cognee.cli._cognee import _discover_commands class TestCliConfig: """Test CLI configuration constants""" @@ -180,10 +27,17 @@ class TestCliConfig: assert DEFAULT_DOCS_URL assert isinstance(DEFAULT_DOCS_URL, str) assert DEFAULT_DOCS_URL.startswith("https://") + assert "cognee.ai" in DEFAULT_DOCS_URL def test_command_descriptions_complete(self): """Test that all expected commands have descriptions""" - expected_commands = ["add", "search", "cognify", "delete", "config"] + commands = _discover_commands() + assert len(commands) > 0 + + expected_commands = [] + for command_class in commands: + command = command_class() + expected_commands.append(command.command_string) for command in expected_commands: assert command in COMMAND_DESCRIPTIONS @@ -224,7 +78,6 @@ class TestCliConfig: for expected_format in expected_formats: assert expected_format in OUTPUT_FORMAT_CHOICES - class TestCliReference: """Test CLI reference protocol""" @@ -262,38 +115,11 @@ class TestCliReference: class TestCliUtilityFunctions: """Test utility functions and edge cases""" - def test_echo_empty_message(self): - """Test echo with empty message""" - with patch("click.secho") as mock_secho: - fmt.echo() - mock_secho.assert_called_once_with("", fg=None, err=False) - - def test_echo_none_message(self): - """Test echo with None message (should not crash)""" - with patch("click.secho") as mock_secho: - # This might raise an exception, which is expected behavior - try: - fmt.echo(None) - except TypeError: - # Expected for None message - pass - def test_multiple_debug_enable_calls(self): """Test multiple calls to enable_debug""" debug.enable_debug() debug.enable_debug() # Should not cause issues - assert debug.is_debug_enabled() + assert debug.is_debug_enabled() is True # Reset for other tests debug._debug_enabled = False - - def test_config_constants_immutability(self): - """Test that config constants are not accidentally modified""" - original_description = CLI_DESCRIPTION - original_url = DEFAULT_DOCS_URL - original_commands = COMMAND_DESCRIPTIONS.copy() - - # These should be the same after any test - assert CLI_DESCRIPTION == original_description - assert DEFAULT_DOCS_URL == original_url - assert COMMAND_DESCRIPTIONS == original_commands