Nette Documentation Preview

syntax
Afirmaciones
************

.[perex]
Las aserciones se utilizan para afirmar que un valor real coincide con un valor esperado. Son métodos de `Tester\Assert`.

Elija las aserciones más precisas. Es mejor `Assert::same($a, $b)` que `Assert::true($a === $b)` porque muestra un mensaje de error significativo en caso de fallo. En el segundo caso sólo obtenemos `false should be true` y no dice nada sobre el contenido de las variables $a y $b.

La mayoría de las aserciones también pueden tener un `$description` opcional que aparece en el mensaje de error si la expectativa falla.

Los ejemplos asumen que el siguiente alias de clase está definido:

```php
use Tester\Assert;
```


Assert::same($expected, $actual, string $description=null) .[method]
--------------------------------------------------------------------
`$expected` debe ser el mismo que `$actual`. Es el mismo que el operador PHP `===`.


Assert::notSame($expected, $actual, string $description=null) .[method]
-----------------------------------------------------------------------
Opuesto a `Assert::same()`, por lo que es el mismo que el operador PHP `!==`.


Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false) .[method]
------------------------------------------------------------------------------------------------------------------------
`$expected` debe ser igual a `$actual`. A diferencia de `Assert::same()`, se ignoran la identidad del objeto, el orden de los pares clave => valor en matrices, y los números decimales marginalmente diferentes, que pueden cambiarse configurando `$matchIdentity` y `$matchOrder`.

Los siguientes casos son idénticos desde el punto de vista de `equal()`, pero no para `same()`:

```php
Assert::equal(0.3, 0.1 + 0.2);
Assert::equal($obj, clone $obj);
Assert::equal(
	['primero' => 11, 'segundo' => 22],
	['segundo' => 22, 'primero' => 11],
);
```

Sin embargo, cuidado, la matriz `[1, 2]` y `[2, 1]` no son iguales, porque sólo difiere el orden de los valores, no los pares clave => valor. El array `[1, 2]` también puede escribirse como `[0 => 1, 1 => 2]` y por tanto `[1 => 2, 0 => 1]` se considerará igual.

También puede utilizar las llamadas [expectativas |#expectations] en `$expected`.


Assert::notEqual($expected, $actual, string $description=null) .[method]
------------------------------------------------------------------------
Opuesto a `Assert::equal()`.


Assert::contains($needle, string|array $actual, string $description=null) .[method]
-----------------------------------------------------------------------------------
Si `$actual` es una cadena, debe contener la subcadena `$needle`. Si es una matriz, debe contener el elemento `$needle` (se compara estrictamente).


Assert::notContains($needle, string|array $actual, string $description=null) .[method]
--------------------------------------------------------------------------------------
Opuesto a `Assert::contains()`.


Assert::hasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
-------------------------------------------------------------------------------------------------------
`$actual` debe ser un array y debe contener la clave `$needle`.


Assert::notHasKey(string|int $needle, array $actual, string $description=null) .[method]{data-version:2.4}
----------------------------------------------------------------------------------------------------------
`$actual` debe ser una matriz y no debe contener la clave `$needle`.


Assert::true($value, string $description=null) .[method]
--------------------------------------------------------
`$value` debe ser `true`, por lo que `$value === true`.


Assert::truthy($value, string $description=null) .[method]
----------------------------------------------------------
`$value` debe ser verdadero, por lo que satisface la condición `if ($value) ...`.


Assert::false($value, string $description=null) .[method]
---------------------------------------------------------
`$value` debe ser `false`, por lo que `$value === false`.


Assert::falsey($value, string $description=null) .[method]
----------------------------------------------------------
`$value` debe ser falsa, por lo que satisface la condición `if (!$value) ...`.


Assert::null($value, string $description=null) .[method]
--------------------------------------------------------
`$value` debe ser `null`, por lo que `$value === null`.


Assert::notNull($value, string $description=null) .[method]
-----------------------------------------------------------
`$value` no debe ser `null`, entonces `$value !== null`.


Assert::nan($value, string $description=null) .[method]
-------------------------------------------------------
`$value` debe ser Not a Number. Utilice únicamente `Assert::nan()` para las pruebas NAN. El valor NAN es muy específico y las aserciones `Assert::same()` o `Assert::equal()` pueden comportarse de forma impredecible.


Assert::count($count, Countable|array $value, string $description=null) .[method]
---------------------------------------------------------------------------------
El número de elementos en `$value` debe ser `$count`. Por tanto, igual que `count($value) === $count`.


Assert::type(string|object $type, $value, string $description=null) .[method]
-----------------------------------------------------------------------------
`$value` debe ser de un tipo determinado. Como `$type` podemos utilizar string:
- `array`
- `list` - array indexado en orden ascendente de claves numéricas desde cero
- `bool`
- `callable`
- `float`
- `int`
- `null`
- `object`
- `resource`
- `scalar`
- `string`
- nombre de clase u objeto directamente entonces debe pasar `$value instanceof $type`


Assert::exception(callable $callable, string $class, string $message=null, $code=null) .[method]
------------------------------------------------------------------------------------------------
Al invocar `$callable` debe lanzarse una excepción de instancia `$class`. Si pasamos `$message`, el mensaje de la excepción debe [coincidir |#assert-match]. Y si pasamos `$code`, código de la excepción debe ser el mismo.

Por ejemplo, esta prueba falla porque el mensaje de la excepción no coincide:

```php
Assert::exception(
	fn() => throw new App\InvalidValueException('Valor cero'),
	App\InvalidValueException::class,
	'El valor es demasiado bajo',
);
```

El `Assert::exception()` devuelve una excepción lanzada, por lo que puede probar una excepción anidada.

```php
$e = Assert::exception(
	fn() => throw new MyException('Algo va mal', 0, new RuntimeException),
	MyException::class,
	'Algo va mal',
);

Assert::type(RuntimeException::class, $e->getPrevious());
```


Assert::error(string $callable, int|string|array $type, string $message=null) .[method]
---------------------------------------------------------------------------------------
Comprueba que la invocación `$callable` genera los errores esperados (es decir, advertencias, avisos, etc.). Como `$type` especificamos una de las constantes `E_...`, por ejemplo `E_WARNING`. Y si pasamos `$message`, el mensaje de error también debe [coincidir |#assert-match] con el patrón. Por ejemplo

```php
Assert::error(
	fn() => $i++,
	E_NOTICE,
	'Undefined variable: i',
);
```

Si el callback genera más errores, debemos esperarlos todos en el orden exacto. En este caso pasamos el array en `$type`:

```php
Assert::error(function () {
	$a++;
	$b++;
}, [
	[E_NOTICE, 'Undefined variable: a'],
	[E_NOTICE, 'Undefined variable: b'],
]);
```

.[note]
Si `$type` es el nombre de la clase, esta aserción se comporta igual que `Assert::exception()`.


Assert::noError(callable $callable) .[method]
---------------------------------------------
Comprueba que la función `$callable` no lanza ningún warning/notice/error o excepción de PHP. Es útil para probar un fragmento de código en el que no hay ninguna otra aserción.


Assert::match(string $pattern, $actual, string $description=null) .[method]
---------------------------------------------------------------------------
`$actual` debe coincidir con `$pattern`. Podemos utilizar dos variantes de patrones: expresiones regulares o comodines.

Si pasamos una expresión regular como `$pattern`, debemos utilizar `~` or `#` para delimitarla. No se admiten otros delimitadores. Por ejemplo test donde `$var` debe contener sólo dígitos hexadecimales:

```php
Assert::match('#^[0-9a-f]$#i', $var);
```

La otra variante es similar a la comparación de cadenas pero podemos utilizar algunos caracteres comodín en `$pattern`:

- `%a%` uno o más de cualquier cosa excepto los caracteres de fin de línea
- `%a?%` cero o más de cualquier cosa excepto los caracteres de fin de línea
- `%A%` uno o más de cualquier cosa incluyendo los caracteres de fin de línea
- `%A?%` cero o más caracteres, incluidos los de final de línea
- `%s%` uno o más caracteres de espacio en blanco excepto los caracteres de final de línea
- `%s?%` cero o más caracteres de espacio en blanco excepto los caracteres de final de línea
- `%S%` uno o más de caracteres excepto el espacio en blanco
- `%S?%` cero o más de caracteres excepto el espacio en blanco
- `%c%` un solo carácter de cualquier tipo (excepto el final de línea)
- `%d%` uno o más dígitos
- `%d?%` cero o más dígitos
- `%i%` valor entero con signo
- `%f%` número en coma flotante
- `%h%` uno o más dígitos HEX
- `%w%` uno o más caracteres alfanuméricos
- `%%` un carácter %

Ejemplos:

```php
# Again, hexadecimal number test
Assert::match('%h%', $var);

# Generalized path to file and line number
Assert::match('Error in file %a% on line %i%', $errorMessage);
```


Assert::matchFile(string $file, $actual, string $description=null) .[method]
----------------------------------------------------------------------------
La aserción es idéntica a [Assert::match() |#assert-match] pero el patrón se carga desde `$file`. Es útil para probar cadenas muy largas. El archivo de prueba es legible.


Assert::fail(string $message, $actual=null, $expected=null) .[method]
---------------------------------------------------------------------
Esta afirmación siempre falla. Sólo es útil. Podemos pasar opcionalmente valores esperados y reales.


Expectativas .[#toc-expectations]
---------------------------------
Si queremos comparar estructuras más complejas con elementos no constantes, las aserciones anteriores pueden no ser suficientes. Por ejemplo, probamos un método que crea un nuevo usuario y devuelve sus atributos como un array. No conocemos el valor hash de la contraseña, pero sabemos que debe ser una cadena hexadecimal. Y lo único que sabemos sobre el siguiente elemento es que debe ser un objeto `DateTime`.

En estos casos, podemos utilizar el `Tester\Expect` dentro del parámetro `$expected` de los métodos `Assert::equal()` y `Assert::notEqual()`, que pueden utilizarse para describir fácilmente la estructura.

```php
use Tester\Expect;

Assert::equal([
	'id' => Expect::type('int'),                   # we expect an integer
	'username' => 'milo',
	'password' => Expect::match('%h%'),            # we expect a string matching pattern
	'created_at' => Expect::type(DateTime::class), # we expect an instance of the class
], User::create(123, 'milo', 'RandomPaSsWoRd'));
```

Con `Expect`, podemos hacer casi las mismas afirmaciones que con `Assert`. Así que tenemos métodos como `Expect::same()`, `Expect::match()`, `Expect::count()`, etc. Además, podemos encadenarlos como:

```php
Expect::type(MyIterator::class)->andCount(5);  # we expect MyIterator and items count is 5
```

O, podemos escribir nuestros propios manejadores de aserción.

```php
Expect::that(function ($value) {
	# return false if expectation fails
});
```


Investigación de aserciones fallidas .[#toc-failed-assertions-investigation]
----------------------------------------------------------------------------
El Comprobador muestra dónde está el error cuando falla una aserción. Cuando comparamos estructuras complejas, el Probador crea volcados de los valores comparados y los guarda en el directorio `output`. Por ejemplo, cuando la prueba imaginaria `Arrays.recursive.phpt` falla, los volcados se guardan de la siguiente manera:

```
app/
└── tests/
	├── output/
	│ ├── Arrays.recursive.actual    # valor real.
	│ └── Arrays.recursive.expected  # valor esperado
	│
	└── Arrays.recursive.phpt        # prueba fallida
```

Podemos cambiar el nombre del directorio por `Tester\Dumper::$dumpDir`.

Afirmaciones

Las aserciones se utilizan para afirmar que un valor real coincide con un valor esperado. Son métodos de Tester\Assert.

Elija las aserciones más precisas. Es mejor Assert::same($a, $b) que Assert::true($a === $b) porque muestra un mensaje de error significativo en caso de fallo. En el segundo caso sólo obtenemos false should be true y no dice nada sobre el contenido de las variables $a y $b.

La mayoría de las aserciones también pueden tener un $description opcional que aparece en el mensaje de error si la expectativa falla.

Los ejemplos asumen que el siguiente alias de clase está definido:

use Tester\Assert;

Assert::same($expected, $actual, string $description=null)

$expected debe ser el mismo que $actual. Es el mismo que el operador PHP ===.

Assert::notSame($expected, $actual, string $description=null)

Opuesto a Assert::same(), por lo que es el mismo que el operador PHP !==.

Assert::equal($expected, $actual, string $description=null, bool $matchOrder=false, bool $matchIdentity=false)

$expected debe ser igual a $actual. A diferencia de Assert::same(), se ignoran la identidad del objeto, el orden de los pares clave ⇒ valor en matrices, y los números decimales marginalmente diferentes, que pueden cambiarse configurando $matchIdentity y $matchOrder.

Los siguientes casos son idénticos desde el punto de vista de equal(), pero no para same():

Assert::equal(0.3, 0.1 + 0.2);
Assert::equal($obj, clone $obj);
Assert::equal(
	['primero' => 11, 'segundo' => 22],
	['segundo' => 22, 'primero' => 11],
);

Sin embargo, cuidado, la matriz [1, 2] y [2, 1] no son iguales, porque sólo difiere el orden de los valores, no los pares clave ⇒ valor. El array [1, 2] también puede escribirse como [0 => 1, 1 => 2] y por tanto [1 => 2, 0 => 1] se considerará igual.

También puede utilizar las llamadas expectativas en $expected.

Assert::notEqual($expected, $actual, string $description=null)

Opuesto a Assert::equal().

Assert::contains($needle, string|array $actual, string $description=null)

Si $actual es una cadena, debe contener la subcadena $needle. Si es una matriz, debe contener el elemento $needle (se compara estrictamente).

Assert::notContains($needle, string|array $actual, string $description=null)

Opuesto a Assert::contains().

Assert::hasKey(string|int $needle, array $actual, string $description=null)

$actual debe ser un array y debe contener la clave $needle.

Assert::notHasKey(string|int $needle, array $actual, string $description=null)

$actual debe ser una matriz y no debe contener la clave $needle.

Assert::true($value, string $description=null)

$value debe ser true, por lo que $value === true.

Assert::truthy($value, string $description=null)

$value debe ser verdadero, por lo que satisface la condición if ($value) ....

Assert::false($value, string $description=null)

$value debe ser false, por lo que $value === false.

Assert::falsey($value, string $description=null)

$value debe ser falsa, por lo que satisface la condición if (!$value) ....

Assert::null($value, string $description=null)

$value debe ser null, por lo que $value === null.

Assert::notNull($value, string $description=null)

$value no debe ser null, entonces $value !== null.

Assert::nan($value, string $description=null)

$value debe ser Not a Number. Utilice únicamente Assert::nan() para las pruebas NAN. El valor NAN es muy específico y las aserciones Assert::same() o Assert::equal() pueden comportarse de forma impredecible.

Assert::count($count, Countable|array $value, string $description=null)

El número de elementos en $value debe ser $count. Por tanto, igual que count($value) === $count.

Assert::type(string|object $type, $value, string $description=null)

$value debe ser de un tipo determinado. Como $type podemos utilizar string:

  • array
  • list – array indexado en orden ascendente de claves numéricas desde cero
  • bool
  • callable
  • float
  • int
  • null
  • object
  • resource
  • scalar
  • string
  • nombre de clase u objeto directamente entonces debe pasar $value instanceof $type

Assert::exception(callable $callable, string $class, string $message=null, $code=null)

Al invocar $callable debe lanzarse una excepción de instancia $class. Si pasamos $message, el mensaje de la excepción debe coincidir. Y si pasamos $code, código de la excepción debe ser el mismo.

Por ejemplo, esta prueba falla porque el mensaje de la excepción no coincide:

Assert::exception(
	fn() => throw new App\InvalidValueException('Valor cero'),
	App\InvalidValueException::class,
	'El valor es demasiado bajo',
);

El Assert::exception() devuelve una excepción lanzada, por lo que puede probar una excepción anidada.

$e = Assert::exception(
	fn() => throw new MyException('Algo va mal', 0, new RuntimeException),
	MyException::class,
	'Algo va mal',
);

Assert::type(RuntimeException::class, $e->getPrevious());

Assert::error(string $callable, int|string|array $type, string $message=null)

Comprueba que la invocación $callable genera los errores esperados (es decir, advertencias, avisos, etc.). Como $type especificamos una de las constantes E_..., por ejemplo E_WARNING. Y si pasamos $message, el mensaje de error también debe coincidir con el patrón. Por ejemplo

Assert::error(
	fn() => $i++,
	E_NOTICE,
	'Undefined variable: i',
);

Si el callback genera más errores, debemos esperarlos todos en el orden exacto. En este caso pasamos el array en $type:

Assert::error(function () {
	$a++;
	$b++;
}, [
	[E_NOTICE, 'Undefined variable: a'],
	[E_NOTICE, 'Undefined variable: b'],
]);

Si $type es el nombre de la clase, esta aserción se comporta igual que Assert::exception().

Assert::noError(callable $callable)

Comprueba que la función $callable no lanza ningún warning/notice/error o excepción de PHP. Es útil para probar un fragmento de código en el que no hay ninguna otra aserción.

Assert::match(string $pattern, $actual, string $description=null)

$actual debe coincidir con $pattern. Podemos utilizar dos variantes de patrones: expresiones regulares o comodines.

Si pasamos una expresión regular como $pattern, debemos utilizar ~ or # para delimitarla. No se admiten otros delimitadores. Por ejemplo test donde $var debe contener sólo dígitos hexadecimales:

Assert::match('#^[0-9a-f]$#i', $var);

La otra variante es similar a la comparación de cadenas pero podemos utilizar algunos caracteres comodín en $pattern:

  • %a% uno o más de cualquier cosa excepto los caracteres de fin de línea
  • %a?% cero o más de cualquier cosa excepto los caracteres de fin de línea
  • %A% uno o más de cualquier cosa incluyendo los caracteres de fin de línea
  • %A?% cero o más caracteres, incluidos los de final de línea
  • %s% uno o más caracteres de espacio en blanco excepto los caracteres de final de línea
  • %s?% cero o más caracteres de espacio en blanco excepto los caracteres de final de línea
  • %S% uno o más de caracteres excepto el espacio en blanco
  • %S?% cero o más de caracteres excepto el espacio en blanco
  • %c% un solo carácter de cualquier tipo (excepto el final de línea)
  • %d% uno o más dígitos
  • %d?% cero o más dígitos
  • %i% valor entero con signo
  • %f% número en coma flotante
  • %h% uno o más dígitos HEX
  • %w% uno o más caracteres alfanuméricos
  • %% un carácter %

Ejemplos:

# Again, hexadecimal number test
Assert::match('%h%', $var);

# Generalized path to file and line number
Assert::match('Error in file %a% on line %i%', $errorMessage);

Assert::matchFile(string $file, $actual, string $description=null)

La aserción es idéntica a Assert::match() pero el patrón se carga desde $file. Es útil para probar cadenas muy largas. El archivo de prueba es legible.

Assert::fail(string $message, $actual=null, $expected=null)

Esta afirmación siempre falla. Sólo es útil. Podemos pasar opcionalmente valores esperados y reales.

Expectativas

Si queremos comparar estructuras más complejas con elementos no constantes, las aserciones anteriores pueden no ser suficientes. Por ejemplo, probamos un método que crea un nuevo usuario y devuelve sus atributos como un array. No conocemos el valor hash de la contraseña, pero sabemos que debe ser una cadena hexadecimal. Y lo único que sabemos sobre el siguiente elemento es que debe ser un objeto DateTime.

En estos casos, podemos utilizar el Tester\Expect dentro del parámetro $expected de los métodos Assert::equal() y Assert::notEqual(), que pueden utilizarse para describir fácilmente la estructura.

use Tester\Expect;

Assert::equal([
	'id' => Expect::type('int'),                   # we expect an integer
	'username' => 'milo',
	'password' => Expect::match('%h%'),            # we expect a string matching pattern
	'created_at' => Expect::type(DateTime::class), # we expect an instance of the class
], User::create(123, 'milo', 'RandomPaSsWoRd'));

Con Expect, podemos hacer casi las mismas afirmaciones que con Assert. Así que tenemos métodos como Expect::same(), Expect::match(), Expect::count(), etc. Además, podemos encadenarlos como:

Expect::type(MyIterator::class)->andCount(5);  # we expect MyIterator and items count is 5

O, podemos escribir nuestros propios manejadores de aserción.

Expect::that(function ($value) {
	# return false if expectation fails
});

Investigación de aserciones fallidas

El Comprobador muestra dónde está el error cuando falla una aserción. Cuando comparamos estructuras complejas, el Probador crea volcados de los valores comparados y los guarda en el directorio output. Por ejemplo, cuando la prueba imaginaria Arrays.recursive.phpt falla, los volcados se guardan de la siguiente manera:

app/
└── tests/
	├── output/
	│ ├── Arrays.recursive.actual    # valor real.
	│ └── Arrays.recursive.expected  # valor esperado
	│
	└── Arrays.recursive.phpt        # prueba fallida

Podemos cambiar el nombre del directorio por Tester\Dumper::$dumpDir.