I’ve been meaning to post some notes about the architecture I’m implementing for CUITs.
- Page objects: Each page, popover, and page tab is fully encapsulated using the page object pattern, hiding the HTML on the page, and providing services to the test scripts. It defines its own page-specific locators, and derives other locators via page compositors.
- Base page: Each page, popover, and page tab derives from a base page that houses the current context and provides locator management.
- Page compositors: Each page includes common elements, such as menu bar and footer, via compositor classes. Each page tab includes common elements, such as page title and tab navigation, via page compositor classes. This composition simplifies the page objects by avoiding redundant code.
- GUI tool encapsulator: The GUI tool interface is fully encapsulated by a single class that performs all searches for controls, and all access to controls. This greatly reduces redundant code elsewhere. It also facilitates instrumentation and diagnostics, such as logging the context when an error occurs. Example: when a menu item is not found, the menu items that did appear are logged.
- Locators: Each control on a page is identified by a locator that lists the attributes needed to find the control. A page object accesses a control by calling a method in the GUI encapsulator, passing it a locator. Example: a page object clicks a button by calling method ClickButton(locator).
- Log: The test log is an XML file consisting of nested sections. These sections correspond to nested code-blocks in the test, and allow a test to “tell its story” in an organized way: steps, substeps, data, verifications. Each section and subsection has a title and, by default, a timestamp and a duration.
Each logged verification includes the expected value, the actual value, the verdict (passed/failed), and a message. A summary at the top of the log gives the counts of passed and failed verifications, and notes whether an exception was thrown. Any thrown exception is captured and logged, including its type, message, and stack trace.
- Verifications: Each verification is performed in a page object, but only at the request of a test script. This eliminates the need for the test script to fetch the actual value, which the page object fetches transparently. The page object also logs the verification.
- Context: A context object is passed to each page constructor, giving access to the test log, the CUIT TestContext object, and other context information.
- Test runner: A test runner object manages the test, including opening and closing the browser and test log, catching and logging exceptions, and logging version and other environmental information.
- Documentation: Documentation is via C# XML documentation, which adds the documentation to the IDE’s IntelliSense. The documentation is also compiled into HTML pages using Doxygen.
Additional documentation covers such topics as test architecture, project best practices, how to “spy” on the application, and various conventions for the test project. This is also captured in the Doxygen.