java - method - patron page factory
Mejores prácticas del modelo de objetos de página en selenio (6)
Cuando está modelando sus objetos de página, ¿cómo trataría una página que tiene forma y alrededor de 50 campos de entrada en ella? ¿Cuál es la mejor práctica aquí?
¿Crearías un objeto de página y escribirías una función separada para cada acción de entrada? ¿O escribirías una función qué parámetros se le pasan e ingresa el texto?
p.ej
public void enterFirstName(String firstName) {
driver.type("firstNameField", firstName);
}
public void enterSecondName(String secondName) {
driver.type("secondNameField", secondName);
}
o
public void fillInForm(String inputFieldName, String text) {
driver.type(inputFieldName, text);
}
Puedo ver en el primer modelo, al escribir pruebas, que las pruebas son más descriptivas, pero si la página contiene demasiados campos de entrada, la creación del objeto de la página se vuelve engorrosa.
Esta publicación también es bastante interesante en la estructuración de las pruebas de selenio en la Página Objetos de Functional Automated Testing Best Practices con Selenium WebDriver
Además de sus métodos enterWhatever()
, generalmente también creo un createWhatever(field1, field2, ...)
, que puedo usar como una ruta rápida para crear cualquier compilación de forma, para usar cuando el propósito real de la prueba es otra cosa Por lo tanto, si necesito crear un cliente para probar el envío de un ticket, la prueba va a la página CreateACustomer
y solo invoca createCustomer(firstName, lastName, emailAddress, ...)
y luego continúa con la tarea con más matices de crear un Ticket usando ese Cliente.
Estoy respondiendo una vieja pregunta para el beneficio de los lectores.
Junto con otras buenas respuestas aquí, me gustaría agregar algunas sugerencias aquí para aquellos que son nuevos en POM.
Los objetos de página es un patrón de diseño bien conocido, ampliamente aceptado por los ingenieros de automatización, para crear un archivo de clase separado para cada página de la aplicación para agrupar todos los elementos como propiedades y sus comportamientos / funcionalidades comerciales como métodos de la clase. Pero tiene pocos problemas para crear una clase para una página, especialmente cuando la página tiene más / diferentes conjuntos de elementos / elementos complejos como un widget de cuadrícula / calendario / una tabla HTML, etc.
La clase puede contener demasiadas responsabilidades para manejar. Debería reestructurarse y dividirse en clases más pequeñas. Es decir, siguiendo la responsabilidad individual responsable .
Mira la imagen aquí para la idea.
Es decir, crea fragmentos de página reutilizables y permite que el objeto de la página principal sirva para los fragmentos de la página.
Mire testautomationguru.com/arquillian-graphene-page-fragments para más información.
La forma en que hago esto en mis formularios es obtener una lista de todas las entradas en la página. A continuación, elimine los elementos de entrada que no se muestran. Después de eso, puedo poner texto válido o no válido en cada una de las entradas. A partir de ahí, veo el resumen de validación para asegurarme de obtener el error correcto o no. Si no es así, registre la excepción.
Lo que esto hace es permitirme ingresar texto en tantas entradas como están en la página, y todavía me permite registrar excepciones y enviarlas por correo electrónico. También capté los campos de texto y contraseña en mi lista y tengo una lista separada para los campos de casilla de verificación y Opciones, ya que hay cosas diferentes que generalmente quiero hacer con ellos.
lo que se reduce a esto es que todo lo que tengo que hacer para probar una página es esto:
for (int i = 0; i < inputs.Count(); i++)
{
//This captures the error message string created in the input validation method
//nextButton is the IWebElement of the button to click to submit the form for validation
//ErrorMessageID is the ID of the Validation Summary display box (i.e. ErrorMessageID = "FormSummary" <asp:ValidationSummary ID="FormSummary" runat="server" CssClass="errorMessage" />
string InputValidationText = utilities.InputValidation(driver, inputs, i, nextButton, ErrorMessageID)
if(InputValidationText != string.Empty)
{
//LogError
}
}
La idea detrás del modelo de objetos de página es que abstrae la implementación de la persona que llama. En el primer mecanismo, lo está haciendo con éxito porque la persona que llama no necesita saber si el nombre del campo de entrada html cambia de "firstName" a "user_first_name", mientras que en su segunda implementación cualquier cambio en la página real tendría que ser filtrado a todas las personas que llaman de su objeto de página.
Si bien puede ser más trabajo por adelantado para crear su objeto de página, si mantiene la encapsulación ahorrará trabajo a largo plazo cuando la página html real inevitablemente cambia.
Por favor, eche un vistazo al archivo readme, https://github.com/yujunliang/seleniumcapsules
Siempre me gusta dividir las cosas en grupos de información relacionada. Por ejemplo, si tengo una clase de usuario, podría dividirla en unas pocas clases más pequeñas: LoginCredentials, ProfileInfo, Settings, etc., pero aún así normalmente tendría una clase de usuario de nivel superior que contiene estas subclases.
Una cosa que sin duda recomendaría sería pasar un objeto a una función de FillForm en lugar de todas esas funciones individuales. Hay algunas grandes ventajas con este enfoque. Primero, podría tener algunos objetos preconfigurados "comunes" que use para muchos de sus casos de prueba. Por ejemplo:
public class FormInfo
{
string Domain;
string Name;
string Category;
// etc...
public FormInfo(string domain, string name, string category)
{
Domain = domain;
Name = name;
Category = category;
// etc...
}
}
// Somewhere in your initialization code
public static FormInfo Info1 = new FormInfo("myDomain1", "myName1", "myCategory1");
public static FormInfo Info2 = new FormInfo("myDomain2", "myName2", "myCategory2");
You can still update one of your common merchants if you need to do something one-off:
// In your test case:
Info1.Category = "blah";
FormPage.FillForm(Info1);
O bien, puede crear un nuevo objeto comercial para un caso de prueba específico si es necesario. También puede hacer cosas como la validación de campo ya sea usando estos objetos, o lo que normalmente hago es romper el patrón del objeto de la página para la validación específica del campo, así que si estoy validando el campo de dominio del comerciante podría hacer esto:
Info1.Domain = null; //This should make the FillForm function skip doing anything with this field.
FormPage.FillForm(Info1);
FormPage.DomainTextBox.Text = "field validation string";
Otra ventaja importante de este enfoque es que si la página se actualiza para agregar, eliminar o modificar campos, solo necesitaría actualizar su objeto FormInfo y la función FillForm, y no necesitaría modificar casos de prueba específicos que llaman a la función FillForm - asumiendo que están usando uno de sus objetos comunes de FormInfo. Otra posibilidad de obtener más cobertura sería configurar uno de los objetos comunes de FormInfo para generar cadenas aleatorias para cada uno de los campos que cumplan con la longitud mínima / máxima y el ciclo entre todos los diferentes caracteres permitidos. Esto le permite obtener algunas pruebas adicionales del mismo conjunto de pruebas, aunque también podría agregar algo de ruido si comienza a obtener resultados de fallas solo de cadenas específicas, así que tenga cuidado.