Slide 1

Slide 1 text

Álvaro de la Mata González CTO y Scrum Master Intexdev SL Grupo Intexmedia @_alvaromg Pruebas Funcionales

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Tipos de tests

Slide 5

Slide 5 text

Tests unitarios Mejorar calidad interna

Slide 6

Slide 6 text

Tests unitarios Mejorar calidad interna Detectar problemas de diseño

Slide 7

Slide 7 text

Tests unitarios Mejorar calidad interna Detectar problemas de diseño Garantizar lógica interna correcta

Slide 8

Slide 8 text

Tests de integración Componente 3 Componente 4 Componente 5 Componente 6 Componente 1 Componente 2

Slide 9

Slide 9 text

Tests funcionales

Slide 10

Slide 10 text

Tests manuales

Slide 11

Slide 11 text

Tests de rendimiento

Slide 12

Slide 12 text

Tests de infraestructura

Slide 13

Slide 13 text

Pirámide ideal de testing

Slide 14

Slide 14 text

¿Por qué hacer tests funcionales?

Slide 15

Slide 15 text

Cliente Equipo Queja Garantiza la calidad funcional del servicio

Slide 16

Slide 16 text

Cliente Equipo Cliente Equipo Queja Solución Garantiza la calidad funcional del servicio

Slide 17

Slide 17 text

Aumenta la satisfacción del cliente

Slide 18

Slide 18 text

Mejora la vida del desarrollador y los que le rodean

Slide 19

Slide 19 text

Elimina tareas repetitivas, reduciendo errores y esfuerzo

Slide 20

Slide 20 text

Da confianza para incluir cambios funcionales

Slide 21

Slide 21 text

"Pequeño trauma" al cubrir proyectos sin pruebas automáticas

Slide 22

Slide 22 text

Documentación viva del proyecto

Slide 23

Slide 23 text

Requiere tener entornos replicados de producción Alta probabilidad de tener tests redundantes No garantiza el correcto funcionamiento de la lógica interna Son frágiles Inconvenientes

Slide 24

Slide 24 text

Mientras desarrollo Cuando integro ramas en control de versiones Cuando hago cambios en producción / preproducción Periódicamente ¿Cuándo hacer tests funcionales?

Slide 25

Slide 25 text

Elementos esperados Cadenas en contenido Respuestas Funcionamiento formularios Redirecciones Procesos ¿Qué debo testear?

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No es necesario testear todo

Slide 28

Slide 28 text

Tipos de navegadores

Slide 29

Slide 29 text

Mink para tests funcionales con PHP

Slide 30

Slide 30 text

Mink para tests funcionales con PHP Unifica la forma de comunicarse con varios tipos de navegadores

Slide 31

Slide 31 text

Headless browser emulators (sin JS) Goutte Tests funcionales HBE (sin JS) HTTP

Slide 32

Slide 32 text

Headless browser emulators (con JS) Zombie.js Phantom.js Tests funcionales HBE (sin JS) HTTP JS

Slide 33

Slide 33 text

Browser controller Selenium Sahi Tests funcionales Browser Controller HTTP

Slide 34

Slide 34 text

Instalando Mink (Composer) { "require": { "behat/mink": "1.6.*" } }

Slide 35

Slide 35 text

Instalando Mink (Phar) $ wget https://github.com/downloads/Behat/Mink/mink.phar

Slide 36

Slide 36 text

Entendiendo Mink $driver = new \Behat\Mink\Driver\GoutteDriver(); Driver Nuestros tests funcionales se comunican con los navegadores a través de los drivers. Todoº driver implementa la interfaz definida en: Behat\Mink\Driver\DriverInterface $clientOptions = array(); $client = new \Behat\Mink\Driver\Goutte\Client(); $client->setClient(new \Guzzle\Http\Client('', $clientOptions)); $driver = new \Behat\Mink\Driver\GoutteDriver($client);

Slide 37

Slide 37 text

Entendiendo Mink // init session: $session = new \Behat\Mink\Session($driver); // start session: $session->start(); Session (controlar el navegador)

Slide 38

Slide 38 text

Entendiendo Mink Session (controlar el navegador) // open some page in browser: $session->visit('http://my_project.dev/some_page.php'); // get the current page URL: echo $session->getCurrentUrl(); // get the response status code: echo $session->getStatusCode(); // get page content: echo $session->getPage()->getContent();

Slide 39

Slide 39 text

Entendiendo Mink // open another page: $session->visit('http://my_project.dev/second_page.php'); // use history controls: $session->reload(); $session->back(); $session->forward(); // evaluate JS expression: echo $session->evaluateScript( "return 'something from browser';" ); // wait for n milliseconds or // till JS expression becomes true: $session->wait( 5000, "$('.suggestions-results').children().length > 0" ); Session (controlar la sesión)

Slide 40

Slide 40 text

Entendiendo Mink // setting browser language: $session->setRequestHeader('Accept-Language', 'fr'); // retrieving response headers: print_r($session->getResponseHeaders()); // set cookie: $session->setCookie('cookie name', 'value'); // get cookie: echo $session->getCookie('cookie name'); // delete cookie: $session->setCookie('cookie name', null); Session (controlar la sesión)

Slide 41

Slide 41 text

Entendiendo Mink $mink = new \Behat\Mink\Mink(); $mink->registerSession('goutte', $goutteSession); $mink->registerSession('sahi', $sahiSession); $mink->setDefaultSessionName('goutte'); // ... $mink->getSession('goutte')->visit('http://my_project.dev/'); $mink->getSession('sahi')->visit('http://my_project.dev/'); Múltiples sesiones

Slide 42

Slide 42 text

Entendiendo Mink $selector = new \Behat\Mink\Selector\NamedSelector(); $handler = new \Behat\Mink\Selector\SelectorsHandler(array( 'named' => $selector )); // XPath query to find the fieldset: $xpath1 = $selector->translateToXPath( array('fieldset', 'id|legend') ); $xpath1 = $handler->selectorToXpath('named', array('fieldset', 'id|legend') ); // XPath query to find the field: $xpath2 = $selector->translateToXPath( array('field', 'id|name|value|label') ); $xpath2 = $handler->selectorToXpath('named', array('field', 'id|name|value|label') ); Selectors (Named)

Slide 43

Slide 43 text

Entendiendo Mink Selectors (Named) Existen varios selectores muy útiles: ● link - encontrar un enlace por href, id, title, img alt o value ● button - encontrar un botón por name, id, value, img alt o title ● link_or_button - para buscar enlaces y botones ● content - para encontrar contenido específico (texto) ● select - para encontrar un elemento select por id, name o label ● checkbox - para encontrar un checkbox por id, name, or label ● radio - para encontrar un radio button por id, name, o label ● file - para encontrar un file input por id, name, o label ● optgroup - para encontrar elementos optgroup por label ● option - para encontrar elementos option por contenido ● table - para encontrar una tabla por id o caption

Slide 44

Slide 44 text

Entendiendo Mink $cssSelector = new \Behat\Mink\Selector\CssSelector(); // generate XPath query out of CSS: echo $cssSelector->translateToXPath('h1 > a'); $handler = new \Behat\Mink\Selector\SelectorsHandler(); $handler->registerSelector('css', $cssSelector); // generate XPath query out of CSS: echo $handler->selectorToXpath('css', 'h1 > a'); Selectors (CSS)

Slide 45

Slide 45 text

Entendiendo Mink $xpath = $handler->selectorToXpath('xpath', '//html'); Selectors (XPATH)

Slide 46

Slide 46 text

Entendiendo Mink $page = $session->getPage(); $page = $mink->getSession('sahi')->getPage(); $fieldElement = $page->find('named', array('field', 'id|name|value|label') ); $elementByCss = $page->find('css', 'h3 > a'); Métodos find* El método find() evalúa un selector en el contenido de la página y devuelve el último elemento que coincida. Si no encuentra ninguno devuelve null.

Slide 47

Slide 47 text

Entendiendo Mink $page = $session->getPage(); $page = $mink->getSession('sahi')->getPage(); $fieldElement = $page->find('named', array('field', 'id|name|value|label') ); $elementByCss = $page->find('css', 'h3 > a'); Métodos find* El método findAll() evalúa un selector en el contenido de la página y devuelve un array con los elementos que lo cumplan.

Slide 48

Slide 48 text

Entendiendo Mink Métodos find* Existen varios atajos útiles: ● findById() - busca un elemento por ID ● findLink() - busca un elemento enlace con el link named selector ● findButton() - busca un elemento button con el button named selector ● findField() - busca un campo con el field named selector

Slide 49

Slide 49 text

Entendiendo Mink $registerForm = $page->find('css', 'form.register'); // find some field INSIDE form with class="register" $field = $registerForm->findField('id|name|value|label'); Consultas anidadas

Slide 50

Slide 50 text

Entendiendo Mink $el = $page->find('css', '.something'); // get tag name: echo $el->getTagName(); // check that element has href attribute: $el->hasAttribute('href'); // get element's href attribute: echo $el->getAttribute('href'); Manipulando la página Behat\Mink\Element\NodeElement proporciona métodos útiles para trabajar con los nodos de la página.

Slide 51

Slide 51 text

Entendiendo Mink // obtener salida eliminando elementos HTML $plainText = $el->getText(); // obtiene la salida tal cual $html = $el->getHtml(); Manipulando la página

Slide 52

Slide 52 text

Entendiendo Mink // check/uncheck checkbox: if ($el->isChecked()) { $el->uncheck(); } $el->check(); // select option in select: $el->selectOption('option value'); // attach file to file input: $el->attachFile('/path/to/file'); // get input value: echo $el->getValue(); // set intput value: $el->setValue('some val'); // press the button: $el->press(); Manipulando formularios

Slide 53

Slide 53 text

Entendiendo Mink $el->click(); $el->doubleClick(); $el->rightClick(); $el->mouseOver(); $el->focus(); $el->blur(); Emulando el ratón

Slide 54

Slide 54 text

Entendiendo Mink $el1 = $page->find(...); $el2 = $page->find(...); $el1->dragTo($el2); Drag & drop

Slide 55

Slide 55 text

Gracias ;)