7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
514 lines
20 KiB
Python
514 lines
20 KiB
Python
"""
|
|
Tests for DecompositionQuestionGenerator.
|
|
|
|
Tests cover:
|
|
- Initialization with default and custom parameters
|
|
- Subject extraction from various question formats
|
|
- Compound question splitting on conjunctions
|
|
- Article removal from subjects
|
|
- LLM response parsing (numbered, bulleted, plain text)
|
|
- Error handling (LLM errors, exceptions)
|
|
- Default question generation for various topic types
|
|
"""
|
|
|
|
from unittest.mock import Mock
|
|
|
|
import pytest
|
|
|
|
from local_deep_research.advanced_search_system.questions.decomposition_question import (
|
|
DecompositionQuestionGenerator,
|
|
)
|
|
|
|
|
|
class TestDecompositionQuestionGeneratorInit:
|
|
"""Tests for DecompositionQuestionGenerator initialization."""
|
|
|
|
def test_init_with_default_max_subqueries(self):
|
|
"""Default max_subqueries is 5."""
|
|
mock_model = Mock()
|
|
generator = DecompositionQuestionGenerator(mock_model)
|
|
assert generator.max_subqueries == 5
|
|
|
|
def test_init_with_custom_max_subqueries(self):
|
|
"""Custom max_subqueries is stored correctly."""
|
|
mock_model = Mock()
|
|
generator = DecompositionQuestionGenerator(mock_model, max_subqueries=3)
|
|
assert generator.max_subqueries == 3
|
|
|
|
def test_init_stores_model(self):
|
|
"""Generator stores the model reference."""
|
|
mock_model = Mock()
|
|
generator = DecompositionQuestionGenerator(mock_model)
|
|
assert generator.model is mock_model
|
|
|
|
|
|
class TestSubjectExtraction:
|
|
"""Tests for subject extraction from question formats."""
|
|
|
|
@pytest.fixture
|
|
def mock_model(self):
|
|
"""Create mock model that returns valid questions."""
|
|
mock = Mock()
|
|
mock.invoke.return_value = Mock(
|
|
content="What is the definition?\nHow does it work?\nWhat are examples?"
|
|
)
|
|
return mock
|
|
|
|
@pytest.fixture
|
|
def generator(self, mock_model):
|
|
"""Create generator instance."""
|
|
return DecompositionQuestionGenerator(mock_model)
|
|
|
|
def test_extract_subject_from_what_is_question(self, generator):
|
|
"""Extract subject from 'what is' question."""
|
|
generator.generate_questions("What is machine learning?", "")
|
|
# Model was invoked with correct subject
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
assert "machine learning" in call_args
|
|
|
|
def test_extract_subject_from_how_does_question(self, generator):
|
|
"""Extract subject from 'how does' question."""
|
|
generator.generate_questions("How does deep learning work?", "")
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
assert "deep learning work" in call_args
|
|
|
|
def test_extract_subject_from_why_is_question(self, generator):
|
|
"""Extract subject from 'why is' question."""
|
|
generator.generate_questions("Why is encryption important?", "")
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
assert "encryption important" in call_args
|
|
|
|
def test_extract_subject_from_who_is_question(self, generator):
|
|
"""Extract subject from 'who is' question."""
|
|
generator.generate_questions("Who is Alan Turing?", "")
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
assert "Alan Turing" in call_args
|
|
|
|
def test_non_question_uses_full_query(self, generator):
|
|
"""Non-question query uses the full query as subject."""
|
|
generator.generate_questions("machine learning algorithms", "")
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
assert "machine learning algorithms" in call_args
|
|
|
|
|
|
class TestCompoundQuestionSplitting:
|
|
"""Tests for splitting compound questions on conjunctions."""
|
|
|
|
@pytest.fixture
|
|
def mock_model(self):
|
|
"""Create mock model."""
|
|
mock = Mock()
|
|
mock.invoke.return_value = Mock(
|
|
content="Q1: What is it?\nQ2: How does it work?\nQ3: Examples?"
|
|
)
|
|
return mock
|
|
|
|
@pytest.fixture
|
|
def generator(self, mock_model):
|
|
"""Create generator instance."""
|
|
return DecompositionQuestionGenerator(mock_model)
|
|
|
|
def test_split_on_and_conjunction(self, generator):
|
|
"""Split compound question at ' and '."""
|
|
generator.generate_questions("What is Python and how is it used?", "")
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
# Should extract "Python" before " and "
|
|
assert "Python" in call_args
|
|
|
|
def test_split_on_or_conjunction(self, generator):
|
|
"""Split compound question at ' or '."""
|
|
generator.generate_questions(
|
|
"What is Java or C++ better for games?", ""
|
|
)
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
assert "Java" in call_args
|
|
|
|
def test_split_on_but_conjunction(self, generator):
|
|
"""Split compound question at ' but '."""
|
|
generator.generate_questions("What is fast but easy to learn?", "")
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
assert "fast" in call_args
|
|
|
|
def test_split_on_when_conjunction(self, generator):
|
|
"""Split compound question at ' when '."""
|
|
generator.generate_questions(
|
|
"What is Python when used for web development?", ""
|
|
)
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
assert "Python" in call_args
|
|
|
|
|
|
class TestArticleRemoval:
|
|
"""Tests for removing articles from subjects."""
|
|
|
|
@pytest.fixture
|
|
def mock_model(self):
|
|
"""Create mock model."""
|
|
mock = Mock()
|
|
mock.invoke.return_value = Mock(content="Q1\nQ2\nQ3")
|
|
return mock
|
|
|
|
@pytest.fixture
|
|
def generator(self, mock_model):
|
|
"""Create generator instance."""
|
|
return DecompositionQuestionGenerator(mock_model)
|
|
|
|
def test_remove_article_a(self, generator):
|
|
"""Remove 'a' article from subject."""
|
|
generator.generate_questions("What is a neural network?", "")
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
# Should not contain "a neural network", just "neural network"
|
|
assert "neural network" in call_args
|
|
|
|
def test_remove_article_an(self, generator):
|
|
"""Remove 'an' article from subject."""
|
|
generator.generate_questions("What is an algorithm?", "")
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
assert "algorithm" in call_args
|
|
|
|
def test_remove_article_the(self, generator):
|
|
"""Remove 'the' article from subject."""
|
|
generator.generate_questions("What is the internet?", "")
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
assert "internet" in call_args
|
|
|
|
|
|
class TestLLMResponseParsing:
|
|
"""Tests for parsing different LLM response formats."""
|
|
|
|
@pytest.fixture
|
|
def generator(self):
|
|
"""Create generator with mock model."""
|
|
mock_model = Mock()
|
|
return DecompositionQuestionGenerator(mock_model)
|
|
|
|
def test_parse_numbered_response(self, generator):
|
|
"""Parse numbered list format (1. 2. 3.)."""
|
|
generator.model.invoke.return_value = Mock(
|
|
content="1. What is the definition?\n2. How does it work?\n3. What are examples?"
|
|
)
|
|
result = generator.generate_questions("test topic", "")
|
|
# Lines starting with "1. " etc. are skipped in first pass, but content is extracted
|
|
assert len(result) >= 0 # May use fallback depending on parsing
|
|
|
|
def test_parse_bulleted_response(self, generator):
|
|
"""Parse bulleted list format (-, *, •)."""
|
|
generator.model.invoke.return_value = Mock(
|
|
content="- What is the definition of topic?\n* How does topic work?\n• What are topic examples?"
|
|
)
|
|
result = generator.generate_questions("test topic", "")
|
|
assert len(result) >= 0
|
|
|
|
def test_parse_plain_text_response(self, generator):
|
|
"""Parse plain text questions (one per line, no bullets)."""
|
|
generator.model.invoke.return_value = Mock(
|
|
content="What is the definition of topic?\nHow does topic work?\nWhat are topic examples?"
|
|
)
|
|
result = generator.generate_questions("test topic", "")
|
|
assert len(result) == 3
|
|
assert "What is the definition of topic?" in result
|
|
|
|
def test_handle_response_with_content_attribute(self, generator):
|
|
"""Handle response object with .content attribute."""
|
|
mock_response = Mock()
|
|
mock_response.content = (
|
|
"Question one here?\nQuestion two here?\nQuestion three here?"
|
|
)
|
|
generator.model.invoke.return_value = mock_response
|
|
result = generator.generate_questions("test", "")
|
|
assert len(result) == 3
|
|
|
|
def test_handle_string_response(self, generator):
|
|
"""Handle plain string response (no .content attribute)."""
|
|
generator.model.invoke.return_value = (
|
|
"Question one here?\nQuestion two here?\nQuestion three here?"
|
|
)
|
|
result = generator.generate_questions("test", "")
|
|
assert len(result) == 3
|
|
|
|
def test_filter_short_lines(self, generator):
|
|
"""Filter out lines shorter than 10 characters."""
|
|
generator.model.invoke.return_value = Mock(
|
|
content="Short\nThis is a valid question longer than ten chars?\nOK"
|
|
)
|
|
result = generator.generate_questions("test", "")
|
|
assert len(result) == 1
|
|
assert "This is a valid question" in result[0]
|
|
|
|
def test_skip_empty_lines(self, generator):
|
|
"""Skip empty lines in response."""
|
|
generator.model.invoke.return_value = Mock(
|
|
content="First valid question here?\n\n\nSecond valid question here?"
|
|
)
|
|
result = generator.generate_questions("test", "")
|
|
assert len(result) == 2
|
|
|
|
def test_respect_max_subqueries_limit(self, generator):
|
|
"""Respect max_subqueries limit."""
|
|
generator.max_subqueries = 2
|
|
generator.model.invoke.return_value = Mock(
|
|
content="Question one here?\nQuestion two here?\nQuestion three here?\nQuestion four here?"
|
|
)
|
|
result = generator.generate_questions("test", "")
|
|
assert len(result) <= 2
|
|
|
|
|
|
class TestLLMErrorHandling:
|
|
"""Tests for handling LLM errors and fallbacks."""
|
|
|
|
@pytest.fixture
|
|
def generator(self):
|
|
"""Create generator with mock model."""
|
|
mock_model = Mock()
|
|
return DecompositionQuestionGenerator(mock_model)
|
|
|
|
def test_handle_no_language_models_error(self, generator):
|
|
"""Fall back to defaults when 'No language models are available'."""
|
|
generator.model.invoke.return_value = Mock(
|
|
content="No language models are available. Please install Ollama."
|
|
)
|
|
result = generator.generate_questions("What is Python?", "")
|
|
# Should return default questions
|
|
assert len(result) > 0
|
|
assert any("Python" in q for q in result)
|
|
|
|
def test_handle_please_install_ollama_error(self, generator):
|
|
"""Fall back to defaults when 'Please install Ollama'."""
|
|
generator.model.invoke.return_value = Mock(
|
|
content="Please install Ollama to use local models."
|
|
)
|
|
result = generator.generate_questions("What is Python?", "")
|
|
assert len(result) > 0
|
|
|
|
def test_handle_llm_exception(self, generator):
|
|
"""Fall back to defaults when LLM raises exception."""
|
|
generator.model.invoke.side_effect = RuntimeError("Connection failed")
|
|
result = generator.generate_questions("What is Python?", "")
|
|
# Should catch exception and return default questions
|
|
assert len(result) > 0
|
|
assert any("Python" in q for q in result)
|
|
|
|
def test_simplified_prompt_fallback(self, generator):
|
|
"""Use simplified prompt when first attempt yields no results."""
|
|
# First call returns unparseable content, second returns valid
|
|
generator.model.invoke.side_effect = [
|
|
Mock(
|
|
content="*\n-\n•"
|
|
), # Only formatting chars, no valid questions
|
|
Mock(
|
|
content="1. Valid question here?\n2. Another valid one?\n3. Third question?"
|
|
),
|
|
]
|
|
generator.generate_questions("test topic", "")
|
|
# Should have called invoke twice
|
|
assert generator.model.invoke.call_count == 2
|
|
|
|
def test_fallback_to_defaults_after_both_prompts_fail(self, generator):
|
|
"""Fall back to defaults when both prompts fail."""
|
|
generator.model.invoke.side_effect = [
|
|
Mock(content=""), # Empty first response
|
|
Mock(content=""), # Empty second response
|
|
]
|
|
result = generator.generate_questions("What is AI?", "")
|
|
# Should return default questions
|
|
assert len(result) > 0
|
|
|
|
|
|
class TestDefaultQuestionGeneration:
|
|
"""Tests for _generate_default_questions method."""
|
|
|
|
@pytest.fixture
|
|
def generator(self):
|
|
"""Create generator with mock model."""
|
|
mock_model = Mock()
|
|
return DecompositionQuestionGenerator(mock_model)
|
|
|
|
def test_csrf_special_case(self, generator):
|
|
"""Generate CSRF-specific questions for CSRF queries."""
|
|
result = generator._generate_default_questions("What is CSRF?")
|
|
assert any("CSRF" in q for q in result)
|
|
assert any("Cross-Site Request Forgery" in q for q in result)
|
|
|
|
def test_csrf_full_name(self, generator):
|
|
"""Generate CSRF-specific questions for full name."""
|
|
result = generator._generate_default_questions(
|
|
"What is cross-site request forgery?"
|
|
)
|
|
assert any("CSRF" in q for q in result)
|
|
|
|
def test_security_topic_questions(self, generator):
|
|
"""Generate security-focused questions for security topics."""
|
|
result = generator._generate_default_questions(
|
|
"What is SQL injection vulnerability?"
|
|
)
|
|
assert any(
|
|
"vulnerability" in q.lower() or "attack" in q.lower()
|
|
for q in result
|
|
)
|
|
|
|
def test_programming_topic_questions(self, generator):
|
|
"""Generate programming-focused questions for programming topics."""
|
|
result = generator._generate_default_questions(
|
|
"Python programming language"
|
|
)
|
|
assert any(
|
|
"features" in q.lower() or "advantages" in q.lower() for q in result
|
|
)
|
|
|
|
def test_short_subject_questions(self, generator):
|
|
"""Generate appropriate questions for short subjects (1-2 words)."""
|
|
result = generator._generate_default_questions("AI")
|
|
assert result[0] == "What is AI?"
|
|
assert any("characteristics" in q for q in result)
|
|
|
|
def test_generic_topic_questions(self, generator):
|
|
"""Generate generic questions for unrecognized topics."""
|
|
result = generator._generate_default_questions(
|
|
"quantum entanglement in physics research"
|
|
)
|
|
assert any("definition" in q.lower() for q in result)
|
|
assert any(
|
|
"components" in q.lower() or "features" in q.lower() for q in result
|
|
)
|
|
|
|
def test_empty_query_questions(self, generator):
|
|
"""Generate generic questions for empty query."""
|
|
result = generator._generate_default_questions("")
|
|
assert len(result) > 0
|
|
assert any("definition" in q.lower() for q in result)
|
|
|
|
def test_default_respects_max_subqueries(self, generator):
|
|
"""Default questions respect max_subqueries limit."""
|
|
generator.max_subqueries = 2
|
|
result = generator._generate_default_questions("What is Python?")
|
|
assert len(result) <= 2
|
|
|
|
|
|
class TestContextHandling:
|
|
"""Tests for context parameter handling."""
|
|
|
|
@pytest.fixture
|
|
def generator(self):
|
|
"""Create generator with mock model."""
|
|
mock_model = Mock()
|
|
mock_model.invoke.return_value = Mock(
|
|
content="Q1: First question?\nQ2: Second question?\nQ3: Third?"
|
|
)
|
|
return DecompositionQuestionGenerator(mock_model)
|
|
|
|
def test_context_included_in_prompt(self, generator):
|
|
"""Context is included in the LLM prompt."""
|
|
context = "This is relevant context information."
|
|
generator.generate_questions("test query", context)
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
assert "This is relevant context information" in call_args
|
|
|
|
def test_long_context_truncated(self, generator):
|
|
"""Long context is truncated to 2000 characters."""
|
|
long_context = "A" * 5000
|
|
generator.generate_questions("test query", long_context)
|
|
call_args = generator.model.invoke.call_args[0][0]
|
|
# Context should be truncated - the prompt won't contain 5000 A's
|
|
assert call_args.count("A") <= 2000
|
|
|
|
def test_empty_context_handled(self, generator):
|
|
"""Empty context is handled gracefully."""
|
|
result = generator.generate_questions("test query", "")
|
|
assert result is not None
|
|
|
|
|
|
class TestIntegration:
|
|
"""Integration tests for complete workflows."""
|
|
|
|
@pytest.fixture
|
|
def mock_model(self):
|
|
"""Create mock model with realistic responses."""
|
|
mock = Mock()
|
|
mock.invoke.return_value = Mock(
|
|
content="""What is the definition of machine learning?
|
|
How does machine learning differ from traditional programming?
|
|
What are common applications of machine learning?
|
|
What are the main types of machine learning algorithms?"""
|
|
)
|
|
return mock
|
|
|
|
@pytest.fixture
|
|
def generator(self, mock_model):
|
|
"""Create generator instance."""
|
|
return DecompositionQuestionGenerator(mock_model)
|
|
|
|
def test_full_workflow_simple_query(self, generator):
|
|
"""Test complete workflow with simple query."""
|
|
result = generator.generate_questions("machine learning", "")
|
|
assert isinstance(result, list)
|
|
assert len(result) > 0
|
|
assert all(isinstance(q, str) for q in result)
|
|
|
|
def test_full_workflow_question_query(self, generator):
|
|
"""Test complete workflow with question-format query."""
|
|
result = generator.generate_questions(
|
|
"What is machine learning and how does it work?", ""
|
|
)
|
|
assert isinstance(result, list)
|
|
assert len(result) > 0
|
|
|
|
def test_full_workflow_with_context(self, generator):
|
|
"""Test complete workflow with context provided."""
|
|
context = "Machine learning is a subset of artificial intelligence."
|
|
result = generator.generate_questions("machine learning", context)
|
|
assert isinstance(result, list)
|
|
assert len(result) > 0
|
|
|
|
|
|
class TestEdgeCases:
|
|
"""Tests for edge cases and boundary conditions."""
|
|
|
|
@pytest.fixture
|
|
def generator(self):
|
|
"""Create generator with mock model."""
|
|
mock_model = Mock()
|
|
mock_model.invoke.return_value = Mock(content="Valid question here?")
|
|
return DecompositionQuestionGenerator(mock_model)
|
|
|
|
def test_whitespace_only_query(self, generator):
|
|
"""Handle whitespace-only query."""
|
|
result = generator.generate_questions(" ", "")
|
|
assert isinstance(result, list)
|
|
|
|
def test_special_characters_in_query(self, generator):
|
|
"""Handle special characters in query."""
|
|
result = generator.generate_questions("What is C++ & C#?", "")
|
|
assert isinstance(result, list)
|
|
|
|
def test_unicode_in_query(self, generator):
|
|
"""Handle unicode characters in query."""
|
|
result = generator.generate_questions("What is 日本語?", "")
|
|
assert isinstance(result, list)
|
|
|
|
def test_very_long_query(self, generator):
|
|
"""Handle very long query."""
|
|
long_query = "What is " + "very " * 100 + "long query?"
|
|
result = generator.generate_questions(long_query, "")
|
|
assert isinstance(result, list)
|
|
|
|
def test_query_with_newlines(self, generator):
|
|
"""Handle query with newline characters."""
|
|
result = generator.generate_questions("What is\nmachine\nlearning?", "")
|
|
assert isinstance(result, list)
|
|
|
|
def test_max_subqueries_zero(self, generator):
|
|
"""Handle max_subqueries set to zero."""
|
|
generator.max_subqueries = 0
|
|
generator.model.invoke.return_value = Mock(content="Q1?\nQ2?\nQ3?")
|
|
result = generator.generate_questions("test", "")
|
|
assert len(result) == 0
|
|
|
|
def test_max_subqueries_one(self, generator):
|
|
"""Handle max_subqueries set to one."""
|
|
generator.max_subqueries = 1
|
|
generator.model.invoke.return_value = Mock(
|
|
content="First question?\nSecond question?\nThird question?"
|
|
)
|
|
result = generator.generate_questions("test", "")
|
|
assert len(result) == 1
|