Skip to content

Add TestRails action#6380

Draft
jpangas wants to merge 2 commits into
mozilla:masterfrom
jpangas:add_test_rails_action
Draft

Add TestRails action#6380
jpangas wants to merge 2 commits into
mozilla:masterfrom
jpangas:add_test_rails_action

Conversation

@jpangas

@jpangas jpangas commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

This pull request introduces support for recording and applying TestRail actions for generated test plans. It adds a new action type for submitting generated test cases to TestRail, implements the handler to make the necessary API calls, and ensures these actions are properly registered and tested. Additionally, the test plan generator agent is updated to automatically record and apply these actions, and new tests are included to verify the integration.

@suhaibmujahid suhaibmujahid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Thank you! Please see my comments, and we can discuss details.

return f"{_base_url()}/index.php?/api/v2/{endpoint.lstrip('/')}"


def _api_request(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us move the part to communicate with TestRail api into its own lib (i.e., libs/testrail-client) like we do for Phabricator (libs/phabricator-client). We could follow that as a reference design.

We keep here the business logic only.

return ActionResult.ok(
{
"suite_id": suite_id,
"suite_url": _suite_url(suite_id),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using url instead of suite_url would avoid know issues, see #6330

Suggested change
"suite_url": _suite_url(suite_id),
"url": _suite_url(suite_id),

ACTION_TYPE = "testrail.submit_test_cases"


def record_test_plan(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this working? I expect not.

Could you please structure it like libs/hackbot-runtime/hackbot_runtime/actions/phabricator.py?


def record_test_plan(
recorder: ActionsRecorder,
test_plan: dict[str, Any],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use pydantic to annotate the inputs like in actions/phabricator.py. That will be provided to the agent to know ho to use the tool.

recorder: ActionsRecorder,
test_plan: dict[str, Any],
*,
reasoning: str = "Upload the generated test cases to TestRail.",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No point in having a default value here. If we have them test case by test case, then having the agent providing reasoning would make sense, but for the test plan itself, it is kind of useless, and we could drop it.


class SubmitTestCasesHandler:
async def apply(self, params: dict[str, Any], ctx: ApplyContext) -> ActionResult:
feature = str(params.get("feature") or "").strip()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a test case handler, but it's currently handling test plans too. :p

I still think it'd be better to allow adding cases one by one. We could have a separate method to create a suite, and another to create a section; each taking a ref. Test cases would then reference that ref, making it available when the cases get applied, so we can retrieve their IDs once they're created and use them to create the cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants