/*
* Copyright (C) 2015 DroidDriver committers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Helper classes for writing an Android UI test framework using DroidDriver.
*
*
UI test framework design principles
*
* A UI test framework should model the UI of the AUT in a hierarchical way to maximize code reuse.
* Common interactions should be abstracted as methods of page objects. Uncommon interactions may
* not be abstracted, but carried out using "driver" directly.
*
* The organization of the entities (pages, components) does not need to strictly follow the AUT
* structure. The UI model can be greatly simplified to make it easy to use.
*
* In general the framework should follow these principles:
*
* - Layered abstraction: at the highest level, methods completely abstract the implementation
* detail. This kind of methods carry out a complex action, usually involving multiple steps.
* At a lower level, methods can expose some details, e.g. clickInstallButton(), which does a
* single action and returns a dialog instance it opens, and let the caller decide how to
* further interact with it. Lastly at the lowest level, you can always use "driver" to access
* any elements if no higher-level methods are available.
* - Instance methods of a page object assume the page is currently shown.
* - If a method opens another page, it should return that page on a best-effort basis. There
* could be exceptions where we let callers determine the type of the new page, but that
* should be considered hacks and be clearly documented.
* - The page object constructors are public so that it's easy to hack as mentioned above, but
* don't abuse it -- typically callers should acquire page objects by calling methods of other
* page objects. The root is the home page of the AUT.
* - Simple dialogs may not merit their own top-level classes, and can be nested as static
* subclasses.
* - Define constants that use values generated from Android resources instead of using string
* literals. For example, call {@link android.content.Context#getResources} to get the
* Resources instance, then call {@link android.content.res.Resources#getResourceName} to get
* the string representation of a resource id, or call {@link
* android.content.res.Resources#getString} to get the localized string of a string resource.
* This gives you compile-time check over incompatible changes.
* - Avoid public constants. Typically clients of a page object are interested in what can be
* done on the page (the content or actions), not how to achieve that (which is an
* implementation detail). The constants used by the page object hence should be encapsulated
* (declared private). Another reason for this item is that the constants may not be real
* constants. Instead they are generated from resources and acquiring the values requires the
* {@link android.content.Context}, which is not available until setUp() is called. If those
* are referenced in static fields of a test class, they will be initialized at class loading
* time and result in a crash.
* - There are cases that exposing public constants is arguably desired. For example, when the
* interaction is trivial (e.g. clicking a button that does not open a new page), and there
* are many similar elements on the page, thus adding distinct methods for them will bloat the
* page object class. In these cases you may define public constants, with a warning that
* "Don't use them in static fields of tests".
*
*
* Common pitfalls
*
*/
package io.appium.droiddriver.helpers;