Page MenuHomePhabricator

[EPIC] OAuth extension critical workflows (for automated tests enhancement)
Open, Needs TriagePublic

Description

We want to improve automated test coverage for the OAuth extension's critical workflows. Each of the critical flows would likely be its own sub-task, where it would be reviewed and decided (then implemented) which test strategy is needed.

Critical flows

  • Developers proposing an OAuth[1/2] consumer (SpecialMWOAuthConsumerRegistration and dependent classes)
  • Developers updating an existing OAuth[1/2] consumer (SpecialMWOAuthConsumerRegistration and dependent classes)
  • An admin reviewing and approving/declining a proposed consumer (SpecialMWOAuthManageConsumers and dependent classes)
  • Users managing approved consumer grants (SpecialMWOAuthManageMyGrants and dependent classes)
  • OAuth1 consumer authorization and token exchange (SpecialMWOAuth/authorize and dependent classes)
  • OAuth2 authorization and token exchange via SessionProvider (/rest.php/oauth2/authorize, /oauth2/access_token, oauth2/reset_secret and dependent classes)
  • Open ID Connect endpoints: Special:MWOAuth/identify (for OAuth 1), oauth2/rest.php/resource/profile (for OAuth 2)

We need to determine which critical flows will be covered by PHPUnit tests and which by E2E testing. PHPUnit is what we already use for PHP/backend side of things, but for E2E testing, we have some options to consider: API testing, Selenium, QUnit, others?

PHPUnit coverage

(source): https://doc.wikimedia.org/cover-extensions/OAuth/src/index.html

Screenshot 2026-01-22 at 6.47.17 PM.png (1×3 px, 692 KB)

Based on the image above, the focus might be Backend, Frontend, Control, and AuthorizationProvider, which together account for most of the classes in the critical flows.

E2E testing

This will mostly cover the action and REST API endpoints (which are multi-requests), such as the authorization and token exchange logic in SpecialMWOAuth. See: https://gitlab.wikimedia.org/tgr/oauth-test-scripts, @Tgr uploaded some useful scripts.

[ ] Decide which framework to use for end-to-end testing. We ended up decided to do everything using PHPUnit.

  • Selenium?
  • QUnit?
  • API testing?
  • other?

Related tasks:

We'll likely be using HandlerTestTrait (for REST handlers), ApiTestCase (for action API), and SpecialPageTestBase (for special pages).

Acceptance criteria
  • Improved PHPUnit test coverage (X%) for critical workflow. X to be decided and updated.
  • E2E tests for critical workflows (PHPUnit)

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript

SpecialMWOAuthManageMyGrants is for users of the app rather than developers.

There are also two OIDC endpoints (Special:OAuth/identify for OAuth 1, oauth/resource/profile for OAuth 2) which are also critical.

I'd maybe separate authorization (done in the session provider) from the handshake / authorization dialog (done in Special:OAuth for OAuth1, that and /oauth2/authorize / /oauth2/access_token for OAuth 2) as they don't have much overlap.

Looks good otherwise. Note that there are multiple variants for these workflows that behave somewhat differently (owner-only vs. normal, for OAuth2 confidential / non-condifential; /authorize vs /authenticate for the authorization dialog; using a refresh token). There are some notes in T341759. I have some local test scripts, I'll upload those shortly.

Wrt the test framework, IMO we should try to steer clear of Selenium which is slow, fragile, and not really needed as we don't have JS frontend code or complex UI that we'd need to test. IMO we should go with something like BrowserKit.

Looks good otherwise. Note that there are multiple variants for these workflows that behave somewhat differently (owner-only vs. normal, for OAuth2 confidential / non-condifential; /authorize vs /authenticate for the authorization dialog; using a refresh token). There are some notes in T341759. I have some local test scripts, I'll upload those shortly.

Thanks! I've incorporated these input in the task description. Looking forward to the test scripts.

Wrt the test framework, IMO we should try to steer clear of Selenium which is slow, fragile, and not really needed as we don't have JS frontend code or complex UI that we'd need to test. IMO we should go with something like BrowserKit.

Ack! As discussed, we can also liaise with QA and have a more elaborate discussion on this topic. Inputs are also welcome from other members of the MWP team.

https://gitlab.wikimedia.org/tgr/oauth-test-scripts
They are pretty barebones but cover the most important things.

Hey folks! I'm very interested in helping out here, since you mentioned liaising with QA. From what I've read so far some general thoughts:

  • Selenium WebdriverIO tests are fragile, I agree with @Tgr 's instinct there. If there's no need to hit Javascript or prove out end-to-end functionality (inclusive of a user's actions), I wouldn't pick that tool.
  • Looking at the oauth-test-scripts, it looks like these are a solid example of API-level testing without any dependencies brought in. I have no objection to that way of handling simple validation - although you'd have to roll your own reporting and all the helpful things that a framework gives you.

Have you considered just pulling in something like PyTest to make it a little more robust and get access to some other things like output in JUnit.xml, which would make it easier to see the results of tests without having to look locally (if this is in CI)?

We'll need to test end-to-end functionality, for some definition of "end-to-end", but 1) we don't need to test JS or UI elements (just HTML form submissions) and 2) OAuth involves both requests from the user's browser to the OAuth server and requests from the application server to the OAuth server, and the latter would be hard to do with Selenium.

oauth-test-scripts was meant an example of what functionality needs to be tested, not something to include in actual test code. I used it on my local machine for manually initiated testing. We could use Python for API testing (IIRC there's some precedent for it) but IMO it would be better to use PHP:

  • Python (or Node.js which I think is the other thing we have a precedent for) is not widely used for MediaWiki tests so we'd incur some integration costs either way
  • everyone is already familiar with PHP (not that it takes that much language knowledge to write tests, but still nice)
  • we can just use PHPUnit and free-ride on the best maintained integration pipeline for reporting
  • more speculatively, but most importanly, it keeps open the possibility of doing internal tests rather than full HTTP requests, similar to how ApiTestCase can do action API queries without actual HTTP calls. I don't think that's possible for other parts of MediaWiki today, but it also doesn't seem hard to enable, and that would allow running complex end-to-end tests in a single PHP process, which is more robust, gives better error information, and allows preparing the environment (globals etc) the same way we can do it in a MediaWikiIntegrationTestCase. So it seems like the more strategic choice to me.

Python's requests library has a bit nicer OAuth 1 support than PHP's Guzzle, but nothing we can't deal with.

Agreed the layer you're looking at (code-level testing of API requests) fits the need - we (QS) have successfully used Pytest in the past but as you mention there's integration costs. Some early attempts at documentation are here. As you can see, it required a fairly robust effort to create and support.

If PHPUnit can handle asserts and produce results in some structured form for future intake into an observability tool, that sounds like a solid plan to me. Strategically speaking, that's what is important long-term as I look to ensure visibility of the health of this feature for others.

So, we've finally agreed to use the PHPUnit framework for all integration and unit tests. Integration tests for simulated/actual HTTP requests (single or multiple) and unit tests for self-contained units that can be tested in isolation.