Test Driven Development

21/26

Lectura

¡Un saludo, Platzinauta!👋🏻

¡Ups! De momento, esta clase no está disponible en nuestra plataforma, pero sí la tenemos en YouTube.

Para no interrumpir tu aprendizaje te dejamos el video y link para que puedas verla en YouTube.

Link a YouTube

Pronto estará disponible en Platzi como el resto de clases.

Gracias por tu comprensión y nunca pares de aprender 💚

Aportes 55

Preguntas 6

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Esto no me lo enseñaron en la universidad. Esta genial!!!

Test Driven Development


Este consiste en primeros las pruebas y luego el software. Etapas:

  1. Escribir un test que falle
  2. Hacer que el código funcione
  3. Eliminar la redundancia

Escribir el siguiente comando para que nos de los resultados del test mas el nombre del test.

php vendor/phpunit/phpunit/phpunit --testdox tests/CalculatorTest.php

Con un alias es más cómodo ejecutar las pruebas:

La clase esta adelanta, vean primero las dos proximas, esta es la ultima de este modulo

TDD: Test Driven Development

Metodología que propone escribir primero la prueba y luego la funcionalidad.

<?php 

use PHPUnit\Framework\TestCase;


class CalculatorTest extends TestCase
{
    public function testAddWillReturnTheSumOfItsParameters()
    {
        $sut = new Calculator();
     
        $this->assertEquals(8, $sut->add(5,3));
        $this->assertEquals(5, $sut->add(5,0));
    }

    public function testAddWillReturnTheSubtractOfItsParameters()
    {
        $sut = new Calculator();
     
        $this->assertEquals(5, $sut->subtract(8,3));
        $this->assertEquals(8, $sut->subtract(10,2));
        $this->assertEquals(2, $sut->subtract(4,2));
    }
    
    public function testAddWillReturnTheMultiplyOfItsParameters()
    {
        $sut = new Calculator();
     
        $this->assertEquals(24, $sut->multiply(8,3));
        $this->assertEquals(20, $sut->multiply(10,2));
        $this->assertEquals(8, $sut->multiply(4,2));
    }

    public function testAddWillReturnTheDivideOfItsParameters()
    {
        $sut = new Calculator();
     
        $this->assertEquals(5, $sut->divide(10,2));
        $this->assertEquals(20, $sut->divide(40,2));
        $this->assertEquals(4, $sut->divide(8,2));
    }
}



<?php
class Calculator
{
    public function add(int $a, int $b): int
    {
        return $a + $b;
    }
    
    public function subtract(int $a, int $b): int
    {
        return $a - $b;
    }
    
    public function multiply(int $a, int $b): int
    {
        return $a * $b;
    }

    public function divide(int $a, int $b): float
    {
        if ($b ===0) {
            throw new InvalidArgumentException('No se puede dividir entre 0');
        }
        return $a / $b;
    }
    
}



Resultados de pruebas:


[email protected]:/var/www/html/platzi/platzi-tdd# vendor/phpunit/phpunit/phpunit --testdox  tests/CalculatorTest.php
PHPUnit 8.2.2 by Sebastian Bergmann and contributors.

Calculator
 ✔ Add will return the sum of its parameters
 ✔ Add will return the subtract of its parameters
 ✔ Add will return the multiply of its parameters
 ✔ Add will return the divide of its parameters

Time: 52 ms, Memory: 4.00 MB

OK (4 tests, 11 assertions)```

Resumen Clase: TDD, desarrollo guiado por las pruebas, es decir escribir primero el código de las pruebas y después desarrollar el código del sistema por medio de las pruebas escritas. Primero Escribimos los test para que falle y después escribimos las funciones con lo mínimo de código para que el código sea un existo, es decir pasar de rojo a verde, después refactorizamos las funciones y volvemos a correr las pruebas para que pasen de nuevo con éxito todas, realizamos esto con todas las funcionalidades de nuestro sistema. Por ultimo podemos decir que el TDD nos obliga a escribir el mínimo de código en nuestras funciones.

Cuando ejecuto me sale que no encuentra la clase Calculator.php pero si la tengo definida


Sin embargo obtengo este error

Pero investigue en internet y con el codigo "require (‘Calculator.php’);"
Si me funciona perfectamente Talvez a alguien le interese
Porque sera

Excelente Profe! Solo que creo que debería haber un curso completo de TDD en PHP utilizando PHPUnit, porque ya lo he visto en 3 cursos y sólo están abarcando la parte básica. ¿Hay planes de un curso así?

Este curso profundiza el tema
Curso de Fundamentos de Pruebas de Software

Si están en linux y creo que igual en cualquier consola bash de Windows, pueden crear un alias para no escribir tantos phpunit:

alias maketests="vendor/phpunit/phpunit/phpunit"

Y simplemente hacen sus pruebas ejecutando “maketests”, como disclaimer, los alias son temporales, cuando apagues tu PC se borrará, pero es útil durante la sesión de trabajo:D!

CalculatorTest.php

<?php

use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase {
    public function testAddWillReturnTheSumOfItsParameter() {
        $sut = new Calculator();

        $this->assertEquals(8, $sut->add(5, 3));
        $this->assertEquals(5, $sut->add(5,0));
    }

    public function testAddWillReturnTheSubtractItsParameter() {
        $sut = new Calculator();

        $this->assertEquals(0, $sut->subtract(3, 3));
        $this->assertEquals(8, $sut->subtract(3, -5));
    }
    
    public function testAddWillReturnTheMultiplyItsParameter() {
        $sut = new Calculator();

        $this->assertEquals(9, $sut->multiply(3, 3));
        $this->assertEquals(20, $sut->multiply(5, 4));
    }

    public function testAddWillReturnTheDivideItsParameter() {
        $sut = new Calculator();

        $this->assertEquals(4, $sut->divide(20, 5));
        $this->assertEquals(2.5, $sut->divide(10, 4));
    }
}

Calculator.php

<?php

class Calculator {
    public function add(int $num1, int $num2) {
        return $num1 + $num2;
    }
    
    public function subtract(int $num1, int $num2) {
        return $num1 - $num2;
    }

    public function multiply(int $num1, int $num2) {
        return $num1 * $num2;
    }

    public function divide(int $num1, int $num2) {
        if(! $num2 == 0) {
            return $num1 / $num2;
        } else {
            throw new InvalidArgumentException("The number is not divide by zero");
        }
    }
}

En python se tienen paquetes para probar las aplicaciones desarrolladas en Python.

En las primeras clases el mentor dice que no es buena practica clean code, iniciar un bloque de código en otra linea:

function test()
{
echo “Esto no es buena practica”;
}

debería ser así:

function test(){
echo “Esto si”;
}

¿Esto es porque en TDD cambia esta "convención"?
  public $n1 = 10;
  public $n2 = 3;

  public function testAddTwoParameters(){
    $calc = new Calculator();
    $this->assertEquals( ($this->n1 + $this->n2), $calc->add($this->n1, $this->n2));
  }

  public function testSubtractTwoParameters(){
    $calc = new Calculator();
    $this->assertEquals( ($this->n1 - $this->n2), $calc->sust($this->n1, $this->n2));
  }

  public function testDivideTwoParameters(){
    $calc = new Calculator();
    $this->assertEquals( ($this->n1 / $this->n2), $calc->div($this->n1, $this->n2));
  }

  public function testMultiplyTwoParameters(){
    $calc = new Calculator();
    $this->assertEquals( ($this->n1 * $this->n2), $calc->mult($this->n1, $this->n2));
  }

es te curso me ha enseñado mas afondo ya que en las univercidaes no tenenseñan afondo lo que en realidad es el tema

Aquí aprendiendo algo de TDD con PHP, interesante. Reto cumplido, comparto el código:
Por cierto, muy buena la regla mnemotécnica y su aplicación con --testdox

<?php
    class Calculator {
        public function add(int $a, int $b) {
            return $a + $b;
        }

        public function sub(int $a, int $b) {
            return $a - $b;
        }

        public function mul(int $a, int $b) {
            return $a * $b;
        }

        public function div(int $a, int $b) {
            return $a / $b;
        }
    }
<?php
    use PHPUnit\Framework\TestCase;
    class CalculatorTest extends TestCase {
        public function testAddWillReturnTheSumOfItsParameters() {
            $sut = new Calculator(); //sut means Subject Under Test
            $this->assertEquals(8, $sut->add(5, 3));
            $this->assertEquals(5, $sut->add(2, 3));
        }

        public function testSubWillReturnTheSubstractionOfItsParameters() {
            $sut = new Calculator(); //sut means Subject Under Test
            $this->assertEquals(5, $sut->sub(8, 3));
            $this->assertEquals(2, $sut->sub(5, 3));
        }

        public function testMulWillReturnTheMultiplicationOfItsParameters() {
            $sut = new Calculator(); //sut means Subject Under Test
            $this->assertEquals(25, $sut->mul(5, 5));
            $this->assertEquals(12, $sut->mul(3, 4));
        }

        public function testDivWillReturnTheDivisionOfItsParameters() {
            $sut = new Calculator(); //sut means Subject Under Test
            $this->assertEquals(3, $sut->div(15, 5));
            $this->assertEquals(6, $sut->div(24, 4));
        }
    }

PHPUnit 8.2.2 by Sebastian Bergmann and contributors.

Calculator
✔ Add will return the sum of its parameters
✔ Sub will return the substraction of its parameters
✔ Mul will return the multiplication of its parameters
✔ Div will return the division of its parameters

Time: 26 ms, Memory: 4.00 MB

OK (4 tests, 8 assertions)

<code> 

Genial !

Mi codigo:

<?php

class Calculator {
  public function add(int $a,int $b) : int {
    return $a + $b;
  }

  public function rest(int $a, int $b) : int {
    return $a - $b;
  }

  public function multiplication(int $a, int $b) : int {
    return $a * $b;
  }
}

Tests:

<?php

use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase {
  public function testAddWillReturnTheSumsOfItsParameters() {
    $sut = new Calculator();

    $this->assertEquals(8 ,$sut->add(5,3));
    $this->assertEquals(5 ,$sut->add(5,0));
  }

  public function testRestWillReturnTheRestOfItsParameters() {
    $sut = new Calculator;

    $this->assertEquals(10 ,$sut->rest(15,5));
    $this->assertEquals(15 ,$sut->rest(25,10));
  }

  public function testMultiplicationWillReturnTheMultiplicationOfItsParameters() {
    $sut = new Calculator;

    $this->assertEquals(75 ,$sut->multiplication(15,5));
    $this->assertEquals(250 ,$sut->multiplication(25,10));
  }
}

Reto cumplido

CalculatorTest.php

<?php

use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase
{
    public function testAddWillReturnTheSumOfItsPAremeters() 
    {
        $sut = new Calculator();

        $this->assertEquals(8, $sut->add(5, 3));
        $this->assertEquals(2, $sut->subtract(6, 4));
        $this->assertEquals(5, $sut->divide(15, 3));
        $this->assertEquals(15, $sut->multiply(5, 3));
    }
}

Calculator.php

<?php

class Calculator 
{
    public function add(int $num1, int $num2) : int
    {
        return $num1 + $num2;
    }

    public function subtract(int $num1, int $num2) : int 
    {
        return $num1 - $num2 ;
    }

    public function divide(int $num1, int $num2) : int 
    {
        return $num1 / $num2;
    }

    public function multiply(int $num1, int $num2) : int
    {
        return $num1 * $num2;
    }
}

Que interesante clase, bastante útil !

Así como existe ->assertEquals, también existen otros metodos de la clase TestCase:
https://gist.github.com/loonies/1255249

totalmente distinta a como trabajo, a aplicar!

La mayoría de universidades siempre enseñan lo mismo, no actualizan sus índices de contenido.

¡Genial!

System Under Test ?

Muy buena explicación. todo entendible.

Algo nuevo que se aprende. Bastante útil!

CalculatorTest.php

use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase {
  public function testAddWillReturnTheSumOfItsParameters()
  {
    $sut = new Calculator();
    $this->assertEquals( 8, $sut->add(5,3) );
    $this->assertEquals( 5, $sut->add(5,0) );
    $this->assertEquals( 2.7, $sut->add(1.2, 1.5) );
  }
  public function testSubWillReturnTheSubstractionOfItsParameters()
  {
    $sut = new Calculator();
    $this->assertEquals( 5, $sut->sub(8,3) );
    $this->assertEquals( -6, $sut->sub(2,8) );
    $this->assertEquals( 0, $sut->sub(15,15) );
    $this->assertEquals( 3.4, $sut->sub(7, 3.6) );
  }
  public function testMulWillReturnTheMultiplicationOfItsParameters()
  {
    $sut = new Calculator();
    $this->assertEquals( 27, $sut->mul(9,3) );
    $this->assertEquals( -8, $sut->mul(4,-2) );
    $this->assertEquals( 0, $sut->mul(5, 0) );
    $this->assertEquals( 2.5, $sut->mul(5, 0.5) );
  }
  public function testDivWillReturnTheDivisionOfItsParameters()
  {
    $sut = new Calculator();
    $this->assertEquals( 3, $sut->div(9,3) );
    $this->assertEquals( 0.4, $sut->div(4,10) );
  }

  public function testDivisionByZeroWillReturnAnException()
  {
    $sut = new Calculator();
    $this->expectException("Exception");
    $this->expectExceptionMessage("No es posible dividir por 0.");
    $sut->div(5,0);
  }
}

Calculator.php

class Calculator
{
  public function add( float $a, float $b ) : float
  {
    return $a + $b;
  }
  public function sub( float $a, float $b ) : float
  {
    return $a - $b;
  }
  public function mul( float $a, float $b) : float
  {
    return $a * $b;
  }
  public function div( float $a, float $b): float
  {
    if($b !== 0) {
      return $a / $b;
    } else {
      throw new \Exception("No es posible dividir por 0.");
    }
  }
}

Todo muy claro. gracias

Mi código de la calculadora:

<?php
/**
 * 
 */
class Calculator
{

  public function add(float $a, float $b) : float {
    return $a + $b;
  }

  public function sub(float $a, float $b) : float {
  	return $a - $b;
  }

  public function mul(float $a, float $b) : float {
  	return $a * $b;
  }
  
  public function div(float $a, float $b) : float {

  	if($b === 0) {
  		throw new Exception("No es posible la división entre 0"); 	
  	}
	return $a / $b;

  }
  
}
?>

Mis pruebas:

<?php

use PHPUnit\Framework\TestCase; 

/**
 * 
 */
class CalculatorTest extends TestCase {
	
	public function testAddWillReturnTheSumOfItsParameters () {
		$sut = new Calculator();

		$this->assertEquals(8, $sut->add(5, 3));
		$this->assertEquals(5, $sut->add(5, 0));
		$this->assertEquals(6, $sut->add(5.5, 0.5));

	}

	public function testSubWillReturnTheSubstractionOfItsParameters(){
    	$sut = new Calculator();
	    
	    $this->assertEquals(2, $sut->sub(4,2));
	    $this->assertEquals(-2, $sut->sub(2,4));
	    $this->assertEquals(0, $sut->sub(1,1));
	    $this->assertEquals(6.5, $sut->sub(10, 3.5) );
 	}	

	public function testMulWillReturnTheSubstractionOfItsParameters(){
    	$sut = new Calculator();
	    
	    $this->assertEquals(8, $sut->mul(4,2));
	    $this->assertEquals(4, $sut->mul(2,2));
	    $this->assertEquals(0, $sut->mul(1,0));
	    $this->assertEquals(-12, $sut->mul(-3, 4));
	    $this->assertEquals(12, $sut->mul(-3, -4));
	    $this->assertEquals(0, $sut->mul(-3, 0));
 	}	

	public function testDivWillReturnTheSubstractionOfItsParameters(){
    	$sut = new Calculator();
	    
	    $this->assertEquals(2, $sut->div(4,2));
	    $this->assertEquals(1, $sut->div(2,2));
	    $this->assertEquals(-4, $sut->div(-12,3));
	    $this->assertEquals(2.5, $sut->div(5,2));
	    $this->assertEquals(-2.5, $sut->div(-5,2));

 	}

	public function testZeroDivWillReturnTheSubstractionOfItsParameters(){

	    $sut = new Calculator();
	    $this->expectException("Exception");
	    $this->expectExceptionMessage("No es posible la división entre 0.");
	    $sut->div(10.5,2);

 	}

}

?>

Como haces para que se detecten los namespaces sin cargar la clase autoload.php???

El tema de los nombres específicos es algo muy presente en el libro Código Limpio o Clean Code, muy bueno!

Cómo es que no me enseñaron nada de testing en la universidad?
Esto es tan extenso e importante 😮

muy buena práctica tdd

Cuál es la forma correcta de aplicar esto en python con Django?

Es un muy buen curso

Así resolví el reto

CalculatorTest.php

<?php

use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase{
  public function testAddWillReturnTheSumOfItsParameters(){
    $sut = new Calculator();

    $this->assertEquals(8, $sut->add(5, 3));
    $this->assertEquals(5, $sut->add(5, 0));
  }

  public function testSubWillReturnTheSubstractionOfItsParameters(){
    $sut = new Calculator();

    $this->assertEquals(2, $sut->sub(5, 3));
    $this->assertEquals(4, $sut->sub(8, 4));
  }

  public function testMultWillReturnTheMultiplicationOfItsParameters(){
    $sut = new Calculator();

    $this->assertEquals(15, $sut->mult(5, 3));
    $this->assertEquals(24, $sut->mult(3, 8));
  }

  public function testDivWillReturnTheDivisionOfItsParameters(){
    $sut = new Calculator();

    $this->assertEquals(5, $sut->div(15, 3));
    $this->assertEquals(8, $sut->div(56, 7));
  }
}

Calculator.php

<?php
class Calculator
{
  public function add(int $num1, int $num2) : int
  {
    return $num1 + $num2;
  }
  public function sub(int $num1, int $num2) : int
  {
    return $num1 - $num2;
  }
  public function mult(int $num1, int $num2) : int
  {
    return $num1 * $num2;
  }
  public function div(int $num1, int $num2) : float
  {
    return $num1 / $num2;
  }
}

😄

class CalculatorTest extends TestCase{
    public function testAddWillBeReturnTheSumOfItsParameters(){
        $sut = new Calculator();

        $this->assertEquals(8, $sut->add(5,3) );
        
    }
    public function testSubstractWillBeReturnTheSubstractionOfItsParameters(){
        $sut = new Calculator();

        $this->assertEquals(2, $sut->substract(5,3) );
        
    }
    public function testMultiplyWillBeReturnTheMultiplicationOfItsParameters(){
        $sut = new Calculator();

        $this->assertEquals(15, $sut->multiply(5,3) );
        
    }
    public function testDivideWillBeReturnTheDivisionOfItsParameters(){
        $sut = new Calculator();

        $this->assertEquals(1, $sut->divide(5,5) );
        $this->assertEquals(2, $sut->divide(4,2) );
    }
}

mi codigo de testing:

<?php

use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase
{
    public function testAddWillReturnTheSumOfItsParameters()
    {
        $sut = new Calculator();

        $this-> assertEquals(8, $sut->add(5, 3));
        $this-> assertEquals(9, $sut->add(7, 2));
    }

    public function testSubstractWillReturnTheSubstractionOfItsParameters()
    {
        $sut = new Calculator();

        $this->assertEquals(6, $sut->substract(6, 0));
        $this->assertEquals(9, $sut->substract(11, 2));
        $this->assertEquals(2, $sut->substract(6, 4));
    }

    public function testMultiplyWillReturnTheMultiplicationOfItsParameters()
    {
        $sut = new Calculator();

        $this->assertEquals(6, $sut->multiply(2, 3));
        $this->assertEquals(10, $sut->multiply(10, 1));
    }

    public function testDivideWillReturnTheDivitionOfItsParameters()
    {
        $sut = new Calculator();

        $this->assertEquals(6, $sut->divide(6, 1));
        $this->assertEquals(9, $sut->divide(27, 3));
        $this->assertEquals(1, $sut->divide(4, 4));
    }
}

y el resultado de las pruebas 😄

TDD Reto:

[email protected] MINGW64 /c/wamp/www/edu/platzi/php/curso_buenas_practicas_de_escritura_de_codigo/platzi-tdd (main)
$ phpunit tests/CalculatorTest.php
PHPUnit 8.2.2 by Sebastian Bergmann and contributors.

Calculator
✔ Add will return the sum of its parameters
✔ Subtract will return the subtraction of its parameters
✔ Multiply will return the product of its parameters
✔ Divide will return the division of its parameters
✔ Divide will throw invalid argument exception when the second parameter equals zero

Time: 138 ms, Memory: 4.00 MB

OK (5 tests, 9 assertions)

PHPUnit en lo personal es la parte que mas me ha costado implementar de todo lo que he aprendido, pero es por la costumbre de realizar el código y probarlo de la manera manual, definitivamente esta es una buena practica que debemos de tener en todos nuestros desarrollos, el Test de los mismos…

Malas práctica para escritura del código declarando variables $a y $b , Según lo aprendido en clase deben declararse descriptivas por ejemplo $numero1 y $numero2 😉!!

Muy interedante. Me pareció genial la lectura de la función como aparece como si fuera una descripción jeje. 😀

Reto:

<?php

use PHPUnit\Framework\TestCase;
use Jchook\AssertThrows\AssertThrows;

class CalculatorTest extends TestCase
{
    use AssertThrows;

    public function testAddWillReturnTheSumOfItsParameters()
    {
        $sut = new Calculator();

        $this->assertEquals(8, $sut->add(5, 3));
        $this->assertEquals(5, $sut->add(5, 0));
    }

    public function testSubtractWillReturnTheSubtractOfItsParameters()
    {
        $sut = new Calculator();

        $this->assertEquals(2, $sut->subtract(5, 3));
        $this->assertEquals(5, $sut->subtract(5, 0));
    }

    public function testMultiplyWillReturnTheProductOfItsParameters()
    {
        $sut = new Calculator();

        $this->assertEquals(15, $sut->multiply(5, 3));
        $this->assertEquals(0, $sut->multiply(5, 0));
    }

    public function testDivideWillReturnTheDivisionOfItsParameters()
    {
        $sut = new Calculator();

        $this->assertEquals(2, $sut->divide(6, 3));
        $this->assertEquals(2.5, $sut->divide(5, 2));
    }

    public function testDivideWillThrowInvalidArgumentExceptionWhenTheSecondParameterEqualsZero()
    {
        $sut = new Calculator();

        $this->assertThrows(InvalidArgumentException::class, function() use ($sut) {
            $sut->divide(5, 0);
        });
    }
}

<?php

class Calculator
{
    public function add(int $a, int $b)
    {
        return $a + $b;
    }

    public function subtract(int $a, int $b)
    {
        return $a - $b;
    }

    public function multiply(int $a, int $b)
    {
        return $a * $b;
    }

    public function divide(int $a, int $b)
    {
        if ($b == 0) {
            throw new \InvalidArgumentException("Division by zero");
        }
        return $a / $b;
    }
}
PHPUnit 8.2.2 by Sebastian Bergmann and contributors.

Calculator
 ✔ Add will return the sum of its parameters
 ✔ Subtract will return the subtraction of its parameters
 ✔ Multiply will return the product of its parameters
 ✔ Divide will return the division of its parameters
 ✔ Divide will throw invalid argument exception when the second parameter equals zero

Para la aserción de excepción en la división por cero hice uso del paquete Exception assertions for PHPUnit

composer require jchook/phpunit-assert-throws

Le hice un fork al repositorio del profe y ahí subí mi reto

[email protected]:RubenchoWeb/platzi-tdd.git```

Muy interesante el tema de las pruebas automatizadas.

Creo que debo retomar PHP tuve problemas al instalar las librerías

super interesante