checkpoint: massive refactor
This commit is contained in:
@@ -4,112 +4,106 @@ import json
|
||||
import conductor_tech_lead
|
||||
|
||||
class TestConductorTechLead(unittest.TestCase):
|
||||
@patch('ai_client.send')
|
||||
@patch('ai_client.set_provider')
|
||||
@patch('ai_client.reset_session')
|
||||
def test_generate_tickets_success(self, mock_reset_session, mock_set_provider, mock_send):
|
||||
# Setup mock response
|
||||
mock_tickets = [
|
||||
{
|
||||
"id": "ticket_1",
|
||||
"type": "Ticket",
|
||||
"goal": "Test goal",
|
||||
"target_file": "test.py",
|
||||
"depends_on": [],
|
||||
"context_requirements": []
|
||||
}
|
||||
]
|
||||
mock_send.return_value = "```json\n" + json.dumps(mock_tickets) + "\n```"
|
||||
|
||||
track_brief = "Test track brief"
|
||||
module_skeletons = "Test skeletons"
|
||||
# Call the function
|
||||
tickets = conductor_tech_lead.generate_tickets(track_brief, module_skeletons)
|
||||
@patch('ai_client.send')
|
||||
@patch('ai_client.set_provider')
|
||||
@patch('ai_client.reset_session')
|
||||
def test_generate_tickets_success(self, mock_reset_session, mock_set_provider, mock_send):
|
||||
# Setup mock response
|
||||
mock_tickets = [
|
||||
{
|
||||
"id": "ticket_1",
|
||||
"type": "Ticket",
|
||||
"goal": "Test goal",
|
||||
"target_file": "test.py",
|
||||
"depends_on": [],
|
||||
"context_requirements": []
|
||||
}
|
||||
]
|
||||
mock_send.return_value = "```json\n" + json.dumps(mock_tickets) + "\n```"
|
||||
track_brief = "Test track brief"
|
||||
module_skeletons = "Test skeletons"
|
||||
# Call the function
|
||||
tickets = conductor_tech_lead.generate_tickets(track_brief, module_skeletons)
|
||||
# Verify set_provider was called
|
||||
mock_set_provider.assert_called_with('gemini', 'gemini-2.5-flash-lite')
|
||||
mock_reset_session.assert_called_once()
|
||||
# Verify send was called
|
||||
mock_send.assert_called_once()
|
||||
args, kwargs = mock_send.call_args
|
||||
self.assertEqual(kwargs['md_content'], "")
|
||||
self.assertIn(track_brief, kwargs['user_message'])
|
||||
self.assertIn(module_skeletons, kwargs['user_message'])
|
||||
# Verify tickets were parsed correctly
|
||||
self.assertEqual(tickets, mock_tickets)
|
||||
|
||||
# Verify set_provider was called
|
||||
mock_set_provider.assert_called_with('gemini', 'gemini-2.5-flash-lite')
|
||||
mock_reset_session.assert_called_once()
|
||||
|
||||
# Verify send was called
|
||||
mock_send.assert_called_once()
|
||||
args, kwargs = mock_send.call_args
|
||||
self.assertEqual(kwargs['md_content'], "")
|
||||
self.assertIn(track_brief, kwargs['user_message'])
|
||||
self.assertIn(module_skeletons, kwargs['user_message'])
|
||||
|
||||
# Verify tickets were parsed correctly
|
||||
self.assertEqual(tickets, mock_tickets)
|
||||
|
||||
@patch('ai_client.send')
|
||||
@patch('ai_client.set_provider')
|
||||
@patch('ai_client.reset_session')
|
||||
def test_generate_tickets_parse_error(self, mock_reset_session, mock_set_provider, mock_send):
|
||||
# Setup mock invalid response
|
||||
mock_send.return_value = "Invalid JSON"
|
||||
|
||||
# Call the function
|
||||
tickets = conductor_tech_lead.generate_tickets("brief", "skeletons")
|
||||
|
||||
# Verify it returns an empty list on parse error
|
||||
self.assertEqual(tickets, [])
|
||||
@patch('ai_client.send')
|
||||
@patch('ai_client.set_provider')
|
||||
@patch('ai_client.reset_session')
|
||||
def test_generate_tickets_parse_error(self, mock_reset_session, mock_set_provider, mock_send):
|
||||
# Setup mock invalid response
|
||||
mock_send.return_value = "Invalid JSON"
|
||||
# Call the function
|
||||
tickets = conductor_tech_lead.generate_tickets("brief", "skeletons")
|
||||
# Verify it returns an empty list on parse error
|
||||
self.assertEqual(tickets, [])
|
||||
|
||||
class TestTopologicalSort(unittest.TestCase):
|
||||
def test_topological_sort_empty(self):
|
||||
tickets = []
|
||||
sorted_tickets = conductor_tech_lead.topological_sort(tickets)
|
||||
self.assertEqual(sorted_tickets, [])
|
||||
def test_topological_sort_empty(self):
|
||||
tickets = []
|
||||
sorted_tickets = conductor_tech_lead.topological_sort(tickets)
|
||||
self.assertEqual(sorted_tickets, [])
|
||||
|
||||
def test_topological_sort_linear(self):
|
||||
tickets = [
|
||||
{"id": "t2", "depends_on": ["t1"]},
|
||||
{"id": "t1", "depends_on": []},
|
||||
{"id": "t3", "depends_on": ["t2"]},
|
||||
]
|
||||
sorted_tickets = conductor_tech_lead.topological_sort(tickets)
|
||||
ids = [t["id"] for t in sorted_tickets]
|
||||
self.assertEqual(ids, ["t1", "t2", "t3"])
|
||||
def test_topological_sort_linear(self):
|
||||
tickets = [
|
||||
{"id": "t2", "depends_on": ["t1"]},
|
||||
{"id": "t1", "depends_on": []},
|
||||
{"id": "t3", "depends_on": ["t2"]},
|
||||
]
|
||||
sorted_tickets = conductor_tech_lead.topological_sort(tickets)
|
||||
ids = [t["id"] for t in sorted_tickets]
|
||||
self.assertEqual(ids, ["t1", "t2", "t3"])
|
||||
|
||||
def test_topological_sort_complex(self):
|
||||
# t1
|
||||
# | \
|
||||
# t2 t3
|
||||
# | /
|
||||
# t4
|
||||
tickets = [
|
||||
{"id": "t4", "depends_on": ["t2", "t3"]},
|
||||
{"id": "t3", "depends_on": ["t1"]},
|
||||
{"id": "t2", "depends_on": ["t1"]},
|
||||
{"id": "t1", "depends_on": []},
|
||||
]
|
||||
sorted_tickets = conductor_tech_lead.topological_sort(tickets)
|
||||
ids = [t["id"] for t in sorted_tickets]
|
||||
# Possible valid orders: [t1, t2, t3, t4] or [t1, t3, t2, t4]
|
||||
self.assertEqual(ids[0], "t1")
|
||||
self.assertEqual(ids[-1], "t4")
|
||||
self.assertSetEqual(set(ids[1:3]), {"t2", "t3"})
|
||||
def test_topological_sort_complex(self):
|
||||
# t1
|
||||
# | \
|
||||
# t2 t3
|
||||
# | /
|
||||
# t4
|
||||
tickets = [
|
||||
{"id": "t4", "depends_on": ["t2", "t3"]},
|
||||
{"id": "t3", "depends_on": ["t1"]},
|
||||
{"id": "t2", "depends_on": ["t1"]},
|
||||
{"id": "t1", "depends_on": []},
|
||||
]
|
||||
sorted_tickets = conductor_tech_lead.topological_sort(tickets)
|
||||
ids = [t["id"] for t in sorted_tickets]
|
||||
# Possible valid orders: [t1, t2, t3, t4] or [t1, t3, t2, t4]
|
||||
self.assertEqual(ids[0], "t1")
|
||||
self.assertEqual(ids[-1], "t4")
|
||||
self.assertSetEqual(set(ids[1:3]), {"t2", "t3"})
|
||||
|
||||
def test_topological_sort_cycle(self):
|
||||
tickets = [
|
||||
{"id": "t1", "depends_on": ["t2"]},
|
||||
{"id": "t2", "depends_on": ["t1"]},
|
||||
]
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
conductor_tech_lead.topological_sort(tickets)
|
||||
self.assertIn("Circular dependency detected", str(cm.exception))
|
||||
def test_topological_sort_cycle(self):
|
||||
tickets = [
|
||||
{"id": "t1", "depends_on": ["t2"]},
|
||||
{"id": "t2", "depends_on": ["t1"]},
|
||||
]
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
conductor_tech_lead.topological_sort(tickets)
|
||||
self.assertIn("Circular dependency detected", str(cm.exception))
|
||||
|
||||
def test_topological_sort_missing_dependency(self):
|
||||
# If a ticket depends on something not in the list, we should probably handle it or let it fail.
|
||||
# Usually in our context, we only care about dependencies within the same track.
|
||||
tickets = [
|
||||
{"id": "t1", "depends_on": ["missing"]},
|
||||
]
|
||||
# For now, let's assume it should raise an error if a dependency is missing within the set we are sorting,
|
||||
# OR it should just treat it as "ready" if it's external?
|
||||
# Actually, let's just test that it doesn't crash if it's not a cycle.
|
||||
# But if 'missing' is not in tickets, it will never be satisfied.
|
||||
# Let's say it raises ValueError for missing internal dependencies.
|
||||
with self.assertRaises(ValueError):
|
||||
conductor_tech_lead.topological_sort(tickets)
|
||||
def test_topological_sort_missing_dependency(self):
|
||||
# If a ticket depends on something not in the list, we should probably handle it or let it fail.
|
||||
# Usually in our context, we only care about dependencies within the same track.
|
||||
tickets = [
|
||||
{"id": "t1", "depends_on": ["missing"]},
|
||||
]
|
||||
# For now, let's assume it should raise an error if a dependency is missing within the set we are sorting,
|
||||
# OR it should just treat it as "ready" if it's external?
|
||||
# Actually, let's just test that it doesn't crash if it's not a cycle.
|
||||
# But if 'missing' is not in tickets, it will never be satisfied.
|
||||
# Let's say it raises ValueError for missing internal dependencies.
|
||||
with self.assertRaises(ValueError):
|
||||
conductor_tech_lead.topological_sort(tickets)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user