Diferencia entre revisiones de «Selenium con DSL»

De Dos Ideas.
Saltar a: navegación, buscar
(Ejemplo)
(Ejemplo)
Línea 6: Línea 6:
 
A continuación mostramos una propuesta de como encarar un test de [[Selenium]] con [[DSL]]. Para el ejemplo, suponemos una aplicación con seguridad, usuarios con diferentes Roles, y diferentes pantallas:
 
A continuación mostramos una propuesta de como encarar un test de [[Selenium]] con [[DSL]]. Para el ejemplo, suponemos una aplicación con seguridad, usuarios con diferentes Roles, y diferentes pantallas:
  
 +
=== AltaDenunciaSeleniumTest ===
 
<code java>
 
<code java>
 
package com.test;
 
package com.test;
Línea 45: Línea 46:
 
De esta forma, escribimos el test de manera que al leer los métodos a los que se invoca, se entiende paso a paso lo que el test realiza, sin confundirnos con la implementación. Utilizando los patrones “method chaining” y “builder” la implementación de la clase Usuario sería una cosa así:
 
De esta forma, escribimos el test de manera que al leer los métodos a los que se invoca, se entiende paso a paso lo que el test realiza, sin confundirnos con la implementación. Utilizando los patrones “method chaining” y “builder” la implementación de la clase Usuario sería una cosa así:
  
 +
=== Usuario ===
 
<code java>
 
<code java>
 
package com.test.selenium.dsl;
 
package com.test.selenium.dsl;
Línea 102: Línea 104:
 
Como vemos en el ejemplo, el método ingresarComoAdministrativo instancia y devuelve un objeto de la clase HomeAdministrativo cuya implementación es:
 
Como vemos en el ejemplo, el método ingresarComoAdministrativo instancia y devuelve un objeto de la clase HomeAdministrativo cuya implementación es:
  
 +
=== HomeAdministrativo ===
 
<code java>
 
<code java>
 
package com.test.selenium.dsl.pagina;
 
package com.test.selenium.dsl.pagina;
Línea 152: Línea 155:
 
Volvemos a utilizar el patrón builder y el método ingresar denuncia devuelve un objeto de la clase AltaDenuncia. De esta manera, cada clase representa a una pantalla de la aplicación, y expone cada funcionalidad que la misma ofrece. AltaDenuncia sería así:
 
Volvemos a utilizar el patrón builder y el método ingresar denuncia devuelve un objeto de la clase AltaDenuncia. De esta manera, cada clase representa a una pantalla de la aplicación, y expone cada funcionalidad que la misma ofrece. AltaDenuncia sería así:
  
 +
=== AltaDenuncia === 
 
<code java>
 
<code java>
 
package com.test.selenium.dsl.pagina;
 
package com.test.selenium.dsl.pagina;
Línea 193: Línea 197:
  
 
</code>
 
</code>
 +
 +
Tanto el cancelar como el aceptar, devuelven la pantalla anterior. Todo se maneja con objetos que representan cada pantalla.
 +
 +
== Conclusiones ==
 +
 +
El resultado de hacer los test de esta manera, es la facilidad de escritura y mantenimiento del test en si mismo. A su vez, se podría diseñar las clases a utilizar en el DSL a conveniencia.

Revisión del 18:54 26 abr 2011

Selenium es una herramienta para pruebas de aplicaciones web. Quién tuvo la posibilidad de utilizarla, sabrá lo poderosa que es la herramienta, la cuál tiene diversas funciones para ejecutar con nuestra aplicación web. Puede ocurrir, que nuestros test de Selenium se vayan complejizando a medida que nuestra aplicación crece, por lo que esta es una posible solución, combinando el poder de Selenium con un enfoque DSL.

Ejemplo

A continuación mostramos una propuesta de como encarar un test de Selenium con DSL. Para el ejemplo, suponemos una aplicación con seguridad, usuarios con diferentes Roles, y diferentes pantallas:

AltaDenunciaSeleniumTest

package com.test;

import static org.junit.Assert.fail;

import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test;

import com.test.selenium.dsl.Usuario;

public class AltaDenunciaSeleniumTest {


   @BeforeClass
   public static void setUpClass() throws Exception {
       Usuario.inicializar();
   }
   @AfterClass
   public static void tearDownClass() throws Exception {
       Usuario.finalizar();
   }
   
   @Test
   public void ingresarConRolAdministrativo_SeDaDeAltaUnaDenuncia() {
       Usuario.ingresarComoAdministrativo()
       .irAingresarDenuncia()
       .completarDenuncia()
       .aceptar()
       .verificarFinalizacionSinErrores()
       .salir();
   }

}

De esta forma, escribimos el test de manera que al leer los métodos a los que se invoca, se entiende paso a paso lo que el test realiza, sin confundirnos con la implementación. Utilizando los patrones “method chaining” y “builder” la implementación de la clase Usuario sería una cosa así:

Usuario

package com.test.selenium.dsl;

import org.openqa.selenium.server.SeleniumServer;

import com.thoughtworks.selenium.DefaultSelenium; import com.thoughtworks.selenium.Selenium; import com.test.selenium.dsl.pagina.HomeAdministrativo;

public class Usuario {

   public static final String TIEMPO_ESPERA = "90000";
   public static final String VELOCIDAD_CERO = "0";
   public static final String VELOCIDAD_TEST = "350";
   
   private static SeleniumServer seleniumServer;
   private static Selenium selenium ;
   
   public static void inicializar() throws Exception {
       seleniumServer = new SeleniumServer();
       seleniumServer.start();
       selenium = new DefaultSelenium( "localhost", 4444, "*chrome", "http://localhost:8585/");
       selenium.start();
   }
   
   public static HomeAdministrativo ingresarComoAdministrativo() {
       Usuario.login("administrativo");
       return new HomeAdministrativo(selenium);        
   }
   
   public static void finalizar() {
       selenium.stop();
       seleniumServer.stop();
   }
   
   private static void login(String username) {
       selenium.setSpeed(VELOCIDAD_TEST);
       selenium.open("");
       selenium.waitForPageToLoad(TIEMPO_ESPERA);
       if (selenium.isElementPresent("relogin")) {
           selenium.click("relogin");
           selenium.waitForPageToLoad(TIEMPO_ESPERA);
       }
       selenium.type("username", username);
       selenium.click("submitbutton");
       selenium.waitForPageToLoad(TIEMPO_ESPERA);
       selenium.setSpeed(VELOCIDAD_CERO);
    
   }


}

Como vemos en el ejemplo, el método ingresarComoAdministrativo instancia y devuelve un objeto de la clase HomeAdministrativo cuya implementación es:

HomeAdministrativo

package com.test.selenium.dsl.pagina;

import static org.junit.Assert.assertEquals;

import com.thoughtworks.selenium.Selenium; import com.test.selenium.dsl.Usuario;

public class HomeAdministrativo {


   private Selenium selenium;
   
   public HomeAdministrativo(Selenium selenium) {
       this.selenium = selenium;
   }
   
   public AltaDenuncia irAingresarDenuncia() {
       selenium.setSpeed(Usuario.VELOCIDAD_TEST);
       selenium.getEval("this.browserbot.getCurrentWindow().selectview('applications')");
       selenium.waitForPageToLoad(Usuario.TIEMPO_ESPERA);
       selenium.click("link=IngresarDenuncia");
       selenium.waitForPageToLoad(Usuario.TIEMPO_ESPERA);
       selenium.setSpeed(Usuario.VELOCIDAD_CERO);
       return new AltaDenuncia(selenium);
   }
   
   
   public void salir() {
       selenium.setSpeed(Usuario.VELOCIDAD_TEST);
       selenium.getEval("this.browserbot.getCurrentWindow().logoutMethod()");
       selenium.waitForPageToLoad(Usuario.TIEMPO_ESPERA);
       if (selenium.isElementPresent("submit")) {
           selenium.click("submit");
           selenium.waitForPageToLoad(Usuario.TIEMPO_ESPERA);
       }
       selenium.setSpeed(Usuario.VELOCIDAD_CERO);
   }
   public HomeAdministrativo verificarFinalizacionSinErrores() {
       assertEquals("IngresarDenuncia",      selenium.getText("link=IngresarDenuncia"));
       return this;
   }

}

Volvemos a utilizar el patrón builder y el método ingresar denuncia devuelve un objeto de la clase AltaDenuncia. De esta manera, cada clase representa a una pantalla de la aplicación, y expone cada funcionalidad que la misma ofrece. AltaDenuncia sería así:

AltaDenuncia

package com.test.selenium.dsl.pagina;

import com.thoughtworks.selenium.Selenium; import com.test.selenium.dsl.Usuario;

public class AltaDenuncia {


   private Selenium selenium;
   
   public AltaDenuncia(Selenium selenium) {
       this.selenium = selenium;
   }
   
   public AltaDenuncia completarDenuncia() {
       
       // Acá iría el código Selenium para completar los campos
       
       return this;
   }
   
   public HomeAdministrativo aceptar() {
       
       selenium.click("OK");
       selenium.waitForPageToLoad(Usuario.TIEMPO_ESPERA);
       
       return new HomeAdministrativo(selenium);
   }
   
   public HomeAdministrativo cancelar() {
       selenium.click("CANCELAR");
       selenium.waitForPageToLoad(Usuario.TIEMPO_ESPERA);
       
       return new HomeAdministrativo(selenium);
   }


}

Tanto el cancelar como el aceptar, devuelven la pantalla anterior. Todo se maneja con objetos que representan cada pantalla.

Conclusiones

El resultado de hacer los test de esta manera, es la facilidad de escritura y mantenimiento del test en si mismo. A su vez, se podría diseñar las clases a utilizar en el DSL a conveniencia.