You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
However, the server exposes 59 tools across 11 modules, and the remaining modules have zero e2e coverage:
Module
# Tools
E2E covered?
datasource.py
1
❌
instance.py
13
❌
monitor.py
2
❌
resource.py
10
❌
schedule.py
7
❌
user.py
2
❌
workflow.py
6
❌
workflow_advanced.py
8
❌
raw.py
4
❌
help.py
1
❌
That means roughly 54 out of 59 tools are only exercised by unit tests (if at all). Real end-to-end behavior — MCP serialization, multi-tenant auth headers, pagination handling, REST API contract drift against a live DolphinScheduler — goes unverified for the vast majority of the surface area.
Proposed Solution
Add dedicated e2e test files per module, following the existing naming convention and fixtures in tests/e2e/conftest.py:
Reuse existing fixtures. The mcp_client and unique_project_name fixtures in conftest.py already handle cluster bootstrapping. Add new fixtures (e.g., workflow_with_tasks, resource_folder) at the module level when downstream tests need pre-created state.
Ordered tests with shared state. Follow the TestXxx class + test_01_*, test_02_* pattern used by TestProjectCRUD so create/list/update/delete flows stay deterministic.
Idempotent cleanup. Every test that creates a resource must clean it up in a final test_NN_teardown step (or a class-level fixture), so repeated runs against the same cluster don't accumulate state.
Assert on MCP wire format, not just payloads. At least one assertion per tool should verify the JSON-RPC structure (no error key, result.content[0].type == "text", parseable JSON body) — _parse_tool_text / _is_error helpers already exist for this.
Negative-path coverage belongs in test_06_negative.py. Module-specific tests should focus on the happy path; move "not found", "bad parameter", "unauthorized" cases to the existing negative test file to avoid duplication.
Tool discovery smoke test. Consider adding a test_00_tool_inventory.py that calls tools/list over MCP and asserts the expected tool names are registered — this catches registration regressions in one shot.
Why it matters
Catch REST API contract drift between dolphin-mcp-pilot and upstream DolphinScheduler releases before users hit them.
Validate multi-tenant per-request auth (X-DS-Token, X-DS-User/X-DS-Password) across the full tool surface, not just projects.
Give contributors confidence that refactors to client.py, middleware.py, or the ds_* helpers don't silently break tool behavior.
Bring e2e coverage in line with the project's "53+ tools" claim in the README.
Background
The e2e test suite (
tests/e2e/) currently focuses on four areas:test_01_smoke.pyds_test_connection)test_02_auth.pytest_03_project_crud.pyds_list_projects,ds_create_project,ds_rename_project,ds_delete_project)test_06_negative.pyHowever, the server exposes 59 tools across 11 modules, and the remaining modules have zero e2e coverage:
datasource.pyinstance.pymonitor.pyresource.pyschedule.pyuser.pyworkflow.pyworkflow_advanced.pyraw.pyhelp.pyThat means roughly 54 out of 59 tools are only exercised by unit tests (if at all). Real end-to-end behavior — MCP serialization, multi-tenant auth headers, pagination handling, REST API contract drift against a live DolphinScheduler — goes unverified for the vast majority of the surface area.
Proposed Solution
Add dedicated e2e test files per module, following the existing naming convention and fixtures in
tests/e2e/conftest.py:test_04_datasource.py—ds_list_datasourcestest_05_instance.py— lifecycle:ds_list_process_instances→ds_run_workflow(fixture) →ds_stop_process_instance/ds_pause_process_instance/ds_resume_process_instance/ds_rerun_process_instance/ds_rerun_from_failure, plus task-level:ds_list_task_instances,ds_get_task_log,ds_force_task_success,ds_skip_task,ds_get_latest_failure_log,ds_delete_process_instance,ds_complement_datatest_07_monitor.py—ds_monitor_masters,ds_monitor_workerstest_08_resource.py— folder/file lifecycle:ds_create_folder→ds_online_create_file→ds_upload_file→ds_list_resources→ds_view_resource→ds_get_resource_by_name→ds_download_resource→ds_update_resource_content→ds_rename_resource→ds_delete_resourcetest_09_schedule.py—ds_list_schedules,ds_set_schedule,ds_online_schedule,ds_offline_schedule,ds_update_schedule_cron,ds_delete_schedule,ds_put_litetest_10_user.py—ds_list_users,ds_list_tenantstest_11_workflow.py—ds_create_workflow→ds_list_workflows→ds_get_workflow→ds_run_workflow→ds_release_workflow→ds_delete_workflowtest_12_workflow_advanced.py—ds_update_workflow,ds_get_task_detail,ds_list_workflow_versions,ds_rollback_workflow_version,ds_clone_workflow,ds_create_dag_workflow,ds_modify_workflow_dag,ds_update_task_paramtest_13_raw.py—ds_raw_get,ds_raw_post,ds_raw_put,ds_raw_deletetest_14_help.py—ds_helpGuidelines
mcp_clientandunique_project_namefixtures inconftest.pyalready handle cluster bootstrapping. Add new fixtures (e.g.,workflow_with_tasks,resource_folder) at the module level when downstream tests need pre-created state.TestXxxclass +test_01_*,test_02_*pattern used byTestProjectCRUDso create/list/update/delete flows stay deterministic.test_NN_teardownstep (or a class-level fixture), so repeated runs against the same cluster don't accumulate state.errorkey,result.content[0].type == "text", parseable JSON body) —_parse_tool_text/_is_errorhelpers already exist for this.test_06_negative.py. Module-specific tests should focus on the happy path; move "not found", "bad parameter", "unauthorized" cases to the existing negative test file to avoid duplication.test_00_tool_inventory.pythat callstools/listover MCP and asserts the expected tool names are registered — this catches registration regressions in one shot.Why it matters
X-DS-Token,X-DS-User/X-DS-Password) across the full tool surface, not just projects.client.py,middleware.py, or theds_*helpers don't silently break tool behavior.References
tests/e2e/