Files
crewAI/tests/test_optional_dependencies.py
Devin AI bccb27ab2e feat: implement crewAI lite version with optional dependencies
- Restructure pyproject.toml to move non-essential dependencies to optional extras
- Add graceful handling for missing optional dependencies in core modules
- Create memory, knowledge, telemetry, visualization, auth, and llm-integrations extras
- Implement helpful ImportError messages directing users to install specific extras
- Add comprehensive test suite for lite installation scenarios
- Maintain backward compatibility with existing installations
- Support minimal core installation with Agent/Crew/Task functionality

Addresses GitHub issue #3026 for lightweight crewAI installation

Co-Authored-By: João <joao@crewai.com>
2025-06-18 10:13:42 +00:00

123 lines
5.9 KiB
Python

"""Test optional dependency handling for crewAI lite version."""
import pytest
from unittest.mock import patch, Mock
import sys
class TestOptionalDependencies:
"""Test that optional dependencies are handled gracefully."""
def test_chromadb_import_error_memory(self):
"""Test that memory functionality raises helpful error without chromadb."""
with patch.dict('sys.modules', {'chromadb': None}):
with patch('crewai.memory.storage.rag_storage.CHROMADB_AVAILABLE', False):
from crewai.memory.storage.rag_storage import RAGStorage
with pytest.raises(ImportError) as exc_info:
RAGStorage("test")
assert "ChromaDB is required" in str(exc_info.value)
assert "crewai[memory]" in str(exc_info.value)
def test_chromadb_import_error_knowledge(self):
"""Test that knowledge functionality raises helpful error without chromadb."""
with patch.dict('sys.modules', {'chromadb': None}):
with patch('crewai.knowledge.storage.knowledge_storage.CHROMADB_AVAILABLE', False):
from crewai.knowledge.storage.knowledge_storage import KnowledgeStorage
with pytest.raises(ImportError) as exc_info:
KnowledgeStorage()
assert "ChromaDB is required" in str(exc_info.value)
assert "crewai[knowledge]" in str(exc_info.value)
def test_pdfplumber_import_error(self):
"""Test that PDF knowledge source raises helpful error without pdfplumber."""
with patch.dict('sys.modules', {'pdfplumber': None}):
from crewai.knowledge.source.pdf_knowledge_source import PDFKnowledgeSource
pdf_source = PDFKnowledgeSource(file_paths=["test.pdf"])
with pytest.raises(ImportError) as exc_info:
pdf_source._import_pdfplumber()
assert "pdfplumber is required" in str(exc_info.value)
assert "crewai[knowledge]" in str(exc_info.value)
def test_pyvis_import_error(self):
"""Test that flow visualization raises helpful error without pyvis."""
with patch.dict('sys.modules', {'pyvis': None}):
with patch('crewai.flow.flow_visualizer.PYVIS_AVAILABLE', False):
from crewai.flow.flow_visualizer import plot_flow
mock_flow = Mock()
with pytest.raises(ImportError) as exc_info:
plot_flow(mock_flow)
assert "Pyvis is required" in str(exc_info.value)
assert "crewai[visualization]" in str(exc_info.value)
def test_auth0_import_error(self):
"""Test that authentication raises helpful error without auth0."""
with patch.dict('sys.modules', {'auth0': None}):
with patch('crewai.cli.authentication.utils.AUTH0_AVAILABLE', False):
from crewai.cli.authentication.utils import validate_token
with pytest.raises(ImportError) as exc_info:
validate_token("fake_token")
assert "Auth0 is required" in str(exc_info.value)
assert "crewai[auth]" in str(exc_info.value)
def test_aisuite_import_error(self):
"""Test that AISuite LLM raises helpful error without aisuite."""
with patch.dict('sys.modules', {'aisuite': None}):
with patch('crewai.llms.third_party.ai_suite.AISUITE_AVAILABLE', False):
from crewai.llms.third_party.ai_suite import AISuiteLLM
with pytest.raises(ImportError) as exc_info:
AISuiteLLM("test-model")
assert "AISuite is required" in str(exc_info.value)
assert "crewai[llm-integrations]" in str(exc_info.value)
def test_opentelemetry_graceful_degradation(self):
"""Test that telemetry degrades gracefully without opentelemetry."""
with patch.dict('sys.modules', {'opentelemetry': None}):
with patch('crewai.telemetry.telemetry.OPENTELEMETRY_AVAILABLE', False):
from crewai.telemetry.telemetry import Telemetry
telemetry = Telemetry()
assert not telemetry.ready
assert telemetry._is_telemetry_disabled()
assert not telemetry._should_execute_telemetry()
def test_embedding_configurator_import_error(self):
"""Test that embedding configurator raises helpful error without chromadb."""
with patch.dict('sys.modules', {'chromadb': None}):
with patch('crewai.utilities.embedding_configurator.CHROMADB_AVAILABLE', False):
from crewai.utilities.embedding_configurator import EmbeddingConfigurator
configurator = EmbeddingConfigurator()
with pytest.raises(ImportError) as exc_info:
configurator.configure_embedder(None)
assert "ChromaDB is required" in str(exc_info.value)
assert "crewai[memory]" in str(exc_info.value) or "crewai[knowledge]" in str(exc_info.value)
def test_docling_import_error(self):
"""Test that docling knowledge source raises helpful error without docling."""
with patch.dict('sys.modules', {'docling': None}):
with patch('crewai.knowledge.source.crew_docling_source.DOCLING_AVAILABLE', False):
from crewai.knowledge.source.crew_docling_source import CrewDoclingSource
with pytest.raises(ImportError) as exc_info:
CrewDoclingSource()
assert "docling package is required" in str(exc_info.value)
assert "uv add docling" in str(exc_info.value)