by Ruslan Khamitov
This article was adapted from a Google Testing on the Toilet (TotT) episode . You can download a printer-friendly version of this TotT episode and post it in your office.
Adding ID attributes to elements can make it much easier to write tests that interact with the DOM (e.g., WebDriver tests). Consider the following DOM with two buttons that differ only by inner text:
Save button
Edit button
<div class="button">Save</div>
<div class="button">Edit</div>
How would you tell WebDriver to interact with the “Save” button in this case? You have several options. One option is to interact with the button using a CSS selector:
div.button
However, this approach is not sufficient to identify a particular button, and there is no mechanism to filter by text in CSS. Another option would be to write an XPath, which is generally fragile and discouraged:
//div[@class='button' and text()='Save']
Your best option is to add unique hierarchical IDs where each widget is passed a base ID that it prepends to the ID of each of its children. The IDs for each button will be:
contact-form .save-button
contact-form .edit-button
In GWT you can accomplish this by overriding onEnsureDebugId()on your widgets . Doing so allows you to create custom logic for applying debug IDs to the sub-elements that make up a custom widget:
@Override protected void onEnsureDebugId (String baseId) {
super .onEnsureDebugId (baseId);
saveButton.ensureDebugId (baseId + ".save-button" );
editButton.ensureDebugId (baseId + ".edit-button" );
}
Consider another example. Let’s set IDs for repeated UI elements in Angular using ng-repeat.
Setting an index can help differentiate between repeated instances of each element:
<tr id="feedback-{{$index}} " class="feedback" ng-repeat="feedback in ctrl.feedbacks" >
In GWT you can do this with ensureDebugId() . Let’s set an ID for each of the table cells:
@UiField FlexTable table;
UIObject.ensureDebugId(table.getCellFormatter().getElement(rowIndex, columnIndex),
baseID + colIndex + "-" + rowIndex );
Take-away: Debug IDs are easy to set and make a huge difference for testing . Please add them early.
Was wondering where you are running WebDriver tests on hosted mode (on a large project) ? If so, how fast you get feedback?
ReplyDeleteGenerally I try not to touch class, especially without some sort of prefixing thing because you don't know what styles properties are out there current and in the future.
ReplyDeleteInstead, what I like to do is use the 'data-*' properties.. So I might have something like,
driver.find_element_by_css_selector("[data-aut-id='figurestable'] tr[data-aut-id='entry{0}']".format(entryId))