GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||
GeezerVison is showing www.mediawiki.org — Selenium/Explanation/Page object pattern - MediaWiki < Selenium | Explanation
This page gives more information about page object pattern mentioned at Selenium/Explanation/Stack page. This tutorial will assume that you are running tests from your machine, targeting MediaWiki-Docker. For more examples see Selenium/Reference/Example Code. Examples will:
PurposeThere are two main purposes of the page object pattern.
Let's describe the two purposes with code samples from MediaWiki Core (as of August 2024). ExampleWith page object patternThe code is split into two files. Please notice how readable import LoginPage from 'wdio-mediawiki/LoginPage.js'; import { createAccount, mwbot } from 'wdio-mediawiki/Api.js'; import { getTestString } from 'wdio-mediawiki/Util.js'; describe( 'User', () => { let password, username, bot; before( async () => { bot = await mwbot(); } ); beforeEach( async () => { await browser.deleteAllCookies(); username = getTestString( 'User-' ); password = getTestString(); } ); it( 'should be able to log in', async () => { // create await createAccount( bot, username, password ); // log in await LoginPage.login( username, password ); // check const actualUsername = await LoginPage.getActualUsername(); expect( actualUsername ).toBe( username ); } ); } ); Please notice that tests/selenium/wdio-mediawiki/LoginPage.js import Page from './Page.js'; class LoginPage extends Page { get username() { return $( '#wpName1' ); } get password() { return $( '#wpPassword1' ); } get loginButton() { return $( '#wpLoginAttempt' ); } async open() { await super.openTitle( 'Special:UserLogin' ); } async getActualUsername() { return browser.execute( () => mw.config.get( 'wgUserName' ) ); } async login( username, password ) { await this.open(); await this.username.setValue( username ); await this.password.setValue( password ); await this.loginButton.click(); } } export default new LoginPage(); Without page object patternLet's compare that to a solution without page object pattern.
import { mwbot, createAccount } from 'wdio-mediawiki/Api.js'; import { getTestString } from 'wdio-mediawiki/Util.js'; // baseUrl is required for our continuous integration. // If you don't have MW_SERVER and MW_SCRIPT_PATH environment variables set // you can probably hardcode it to something like this: // const baseUrl = 'http://localhost:8080/wiki/'; const baseUrl = `${ process.env.MW_SERVER }${ process.env.MW_SCRIPT_PATH }/index.php?title=`; describe( 'User', () => { let password, username, bot; before( async () => { bot = await mwbot(); } ); beforeEach( async () => { username = getTestString( 'User-' ); password = getTestString(); } ); it( 'should be able to log in without page object', async () => { // create await createAccount( bot, username, password ); // log in await browser.url( `${ baseUrl }Special:UserLogin` ); await $( '#wpName1' ).setValue( username ); await $( '#wpPassword1' ).setValue( password ); await $( '#wpLoginAttempt' ).click(); // check const actualUsername = await browser.execute( () => mw.config.get( 'wgUserName' ) ); expect( actualUsername ).toBe( username ); } ); } ); ConclusionWith page object pattern, the framework is more complex, there are more files (two instead of one) and there is more overall code, but the tests are more readable and more maintainable. Without page object pattern, the framework is simpler, there are less files (one instead of two) and there is less overall code, but the tests are less readable and less maintainable. To keep this page short, I've selected a simple example. If the test suite is logging the user in a lot, without page object pattern, code for logging in would have to be copy/pasted, leading to duplication and harder maintenance. With the page object pattern, logging in is just a call to More information
| ||
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |