5. Idea of page
object
• Based on OOP principles
• One class describes one page
• Pages can inherit one from
another
• Additional layer of abstraction
for our tests
• Extracts elements
manipulations from test logic
Page
Notes
RecycleBin
Archive
createNote (title, body) {}
deleteNote (index) {}
archiveNote (index) {}
changeNoteColor (index, color) {}
editNote (index, title, body) {}
deleteNoteForever (index) {}
restoreNote (index) {}
unarchiveNote (index) {}
deleteNote (index) {}
changeNoteColor (index, color) {}
editNote (index, title, body) {}
openRecycleBinPage()
openArchivePage()
openNotesPage()
6. Idea of page
object
• Elements are belongs to
object instance, usually as
class fields or instance
attribute
• Elements should be
initialized in proper time
• Methods describe actions
that user can do on the page
NotesPage
headerMenuButton
openRecycleBinPageLink
openArchivePageLink
openNotesPageLink
createNoteField
deleteNoteButtons
archiveNoteButtons
changeColorButtons
…
7. Best practices
• Page object methods should do
only what specified in their
name
• This means not less than needed
to make action completed, not
more than needed to make
action completed
• Use inheritance, composition,
use reliable locators, chain
searching of elements
• If you have repeatable complex
actions in your tests – use
models to reduce copy-paste
10. Idea of
Fragments
• Reproduce the same structure of
objects on the page that we
already have in our application
• Now page is not the smallest
object in framework
• Break fragments into smaller
fragments
• Group smaller fragments into
bigger fragments
• Reuse methods of child fragments
in parent fragment
NoteFragment
INCLUDES fragments:
ArchiveButton
ChangeColorButton
DeleteButton
getTitle()
getBody()
edit(title, body)
changeColor(color)
delete()
archive()
11. Fragments
• Use chaining for elements
search where possible
• Search inside element
instead searching
everywhere on the page
• As an option, pass root
element into constructor
as parameter, and use it
to make all searches
inside this element
let deleteButton = browser.element(by.css('button.delete'))
Better:
Bad:
12. Idea of
Fragments
• Inherit one fragment from
another
• Use power of OOP
• Introduce types in
languages without strict
types (JS, Python) to
enable autocomplete in
IDE
• Use interfaces, abstract
classes to introduce
parent objects
NoteFragment
ArchivedNoteFragment
DeletedNoteFragment
AbstractNoteFragment
???
Fragment
14. Custom
collections of
own fragments
• Create custom collections with
your fragments
• Works like usual array/list/etc , but
extended with your own methods
• Iterate thru collection, apply filters
• Best works for things like search
results
• Feature state:
• Java – tested and used in prod
• Python – not investigated (3rd party
libs exists)
• JS (ProtractorJS) – testing and bug
fixing
NotesArrayFragment
get(index) -> returns NoteFragment
count()
map()
filter()
…
hasNoteWithTitle(title)
hasNoteWithTitle(body)
hasNoteWithColor(title)
15. Inherit from
WebElement
object
• Your fragments now valid
WebElements
• Your custom fragments can be
passed to any methods that
require WebElement as parameter
• Override existing WebElement
methods, such as isDisplayed() for
even more flexibility (if needed)
WebElement
Object
Inheritance
chain
FooFragment
BarFragment
17. Benefits
• Nice reusing of components across
different pages or even projects
• Better stability on locators changes
• Logic spited across smaller parts –
easier to change
• Cleaner code
• Easier to understand because
everything has it own names
• Can be applied to any
tool/programming language. Also
works for non-web applications
18. Hard parts
• Requires good understanding of
OOP principles
• Requires to write more code
• Might be not needed in tiny
projects – best works in
applications with a lot of similar
fragments
• Idea is not used widely. Everyone
building own approach
• Additional framework layer in
your code