Assertions
As afirmações são usadas para afirmar que um valor real corresponde a um valor esperado. Eles são métodos do
Tester\Assert
.
Escolha as afirmações mais precisas. É melhor Assert::same($a, $b)
do que Assert::true($a === $b)
porque exibe uma mensagem de erro significativa em caso de falha. No segundo caso, obtemos apenas
false should be true
e não diz nada sobre o conteúdo das variáveis $a e $b.
A maioria das afirmações também pode ter um $description
opcional que aparece na mensagem de erro se a
expectativa falhar.
Os exemplos assumem que a seguinte classe está definida:
use Tester\Assert;
Assert::same($expected, $actual, ?string $description=null)
$expected
deve ser o mesmo que $actual
. É o mesmo que o operador de PHP ===
.
Assert::notSame($expected, $actual, ?string $description=null)
Ao contrário de Assert::same()
, então é o mesmo que o operador PHP !==
.
Assert::equal($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false)
$expected
deve ser o mesmo que $actual
. Ao contrário de Assert::same()
, a identidade
do objeto, a ordem dos pares de chaves ⇒ valor em arrays e números decimais marginalmente diferentes são ignorados, o que
pode ser alterado através da configuração $matchIdentity
e $matchOrder
.
Os seguintes casos são idênticos do ponto de vista de equal()
, mas não para same()
:
Assert::equal(0.3, 0.1 + 0.2);
Assert::equal($obj, clone $obj);
Assert::equal(
['first' => 11, 'second' => 22],
['second' => 22, 'first' => 11],
);
Entretanto, tenha cuidado, a matriz [1, 2]
e [2, 1]
não são iguais, porque apenas a ordem dos
valores é diferente, não a chave ⇒ pares de valores. A matriz [1, 2]
também pode ser escrito como
[0 => 1, 1 => 2]
e, portanto [1 => 2, 0 => 1]
serão considerados iguais.
Você também pode usar as chamadas expectativas em $expected
.
Assert::notEqual($expected, $actual, ?string $description=null)
Oposto a Assert::equal()
.
Assert::contains($needle, string|array $actual, ?string $description=null)
Se $actual
for um fio, ele deve conter o substrato $needle
. Se for uma matriz, deve conter
o elemento $needle
(é comparado estritamente).
Assert::notContains($needle, string|array $actual, ?string $description=null)
Oposto a Assert::contains()
.
Assert::hasKey(string|int $needle, array $actual, ?string $description=null)
$actual
deve ser uma matriz e deve conter a chave $needle
.
Assert::notHasKey(string|int $needle, array $actual, ?string $description=null)
$actual
deve ser uma matriz e não deve conter a chave $needle
.
Assert::true($value, ?string $description=null)
$value
deve ser true
, portanto $value === true
.
Assert::truthy($value, ?string $description=null)
$value
deve ser verdadeira, portanto satisfaz a condição if ($value) ...
.
Assert::false($value, ?string $description=null)
$value
deve ser false
, portanto $value === false
.
Assert::falsey($value, ?string $description=null)
$value
deve ser falso, por isso satisfaz a condição if (!$value) ...
.
Assert::null($value, ?string $description=null)
$value
deve ser null
, portanto $value === null
.
Assert::notNull($value, ?string $description=null)
$value
não deve ser null
, portanto $value !== null
.
Assert::nan($value, ?string $description=null)
$value
não deve ser um número. Use apenas o Assert::nan()
para testes NAN. O valor do NAN é muito
específico e as afirmações Assert::same()
ou Assert::equal()
podem se comportar de forma
imprevisível.
Assert::count($count, Countable|array $value, ?string $description=null)
O número de elementos em $value
deve ser $count
. Portanto, o mesmo que
count($value) === $count
.
Assert::type(string|object $type, $value, ?string $description=null)
$value
deve ser de um determinado tipo. Como $type
, podemos usar cordel:
array
list
– matriz indexada em ordem ascendente de chaves numéricas a partir de zerobool
callable
float
int
null
object
resource
scalar
string
- nome da classe ou objeto deve então passar diretamente
$value instanceof $type
Assert::exception(callable $callable, string $class, ?string $message=null, $code=null)
Em $callable
deve ser lançada uma exceção de instância $class
. Se passarmos
$message
, a mensagem da exceção deve coincidir. E se passarmos $code
,
o código da exceção deve ser o mesmo.
Por exemplo, este teste falha porque a mensagem da exceção não corresponde:
Assert::exception(
fn() => throw new App\InvalidValueException('Zero value'),
App\InvalidValueException::class,
'Value is to low',
);
O Assert::exception()
retorna uma exceção lançada, para que você possa testar uma exceção aninhada.
$e = Assert::exception(
fn() => throw new MyException('Something is wrong', 0, new RuntimeException),
MyException::class,
'Something is wrong',
);
Assert::type(RuntimeException::class, $e->getPrevious());
Assert::error(string $callable, int|string|array $type, ?string $message=null)
Verifica se a invocação $callable
gera os erros esperados (ou seja, avisos, avisos, etc.). Como
$type
, especificamos uma das constantes E_...
, por exemplo E_WARNING
. E, se passar
$message
, a mensagem de erro também deve corresponder ao padrão. Por exemplo:
Assert::error(
fn() => $i++,
E_NOTICE,
'Undefined variable: i',
);
Se a ligação de retorno gera mais erros, devemos esperar todos eles na ordem exata. Neste caso, passamos a matriz em
$type
:
Assert::error(function () {
$a++;
$b++;
}, [
[E_NOTICE, 'Undefined variable: a'],
[E_NOTICE, 'Undefined variable: b'],
]);
Se $type
é nome de classe, esta afirmação se comporta da mesma forma que
Assert::exception()
.
Assert::noError(callable $callable)
Verifica se a função $callable
não lança nenhum aviso/notificação/erro ou exceção em PHP. É útil para
testar um pedaço de código onde não há outra asserção.
Assert::match(string $pattern, $actual, ?string $description=null)
$actual
Devemos corresponder a $pattern
. Podemos utilizar duas variantes de padrões: expressões
regulares ou wildcards.
Se passarmos uma expressão regular como $pattern
, devemos usar ~
or #
para
delimitá-la. Outros delimitadores não são suportados. Por exemplo, teste onde $var
deve conter apenas dígitos
hexadecimais:
Assert::match('#^[0-9a-f]$#i', $var);
A outra variante é semelhante à comparação de cordas, mas podemos usar alguns chars selvagens em
$pattern
:
%a%
um ou mais de qualquer coisa, exceto os caracteres de fim de linha%a?%
zero ou mais de qualquer coisa, exceto os caracteres de fim de linha%A%
um ou mais de qualquer coisa, incluindo os caracteres de fim de linha%A?%
zero ou mais de qualquer coisa, incluindo os caracteres de fim de linha%s%
um ou mais caracteres de espaço branco, exceto os caracteres de fim de linha%s?%
zero ou mais caracteres de espaço branco, exceto os caracteres de fim de linha%S%
um ou mais caracteres, exceto o espaço branco%S?%
zero ou mais caracteres, exceto para o espaço branco%c%
um único personagem de qualquer tipo (exceto para o final da linha)%d%
um ou mais dígitos%d?%
zero ou mais dígitos%i%
valor inteiro assinado%f%
número do ponto flutuante%h%
um ou mais dígitos do HEX%w%
um ou mais caracteres alfanuméricos%%
um % de caráter
Exemplos:
# 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)
A afirmação é idêntica a Assert::match() mas o padrão é carregado a partir de
$file
. É útil para testes de cordas muito longas. Os arquivos de teste podem ser lidos.
Assert::fail(string $message, $actual=null, $expected=null)
Esta afirmação sempre falha. É apenas útil. Opcionalmente, podemos passar os valores esperados e reais.
Expectativas
Se quisermos comparar estruturas mais complexas com elementos não-constantes, as afirmações acima podem não ser
suficientes. Por exemplo, testamos um método que cria um novo usuário e devolve seus atributos como uma matriz. Não sabemos
o valor do hash da senha, mas sabemos que ela deve ser uma string hexadecimal. E a única coisa que sabemos sobre o próximo
elemento é que ele deve ser um objeto DateTime
.
Nestes casos, podemos usar o Tester\Expect
dentro do parâmetro $expected
dos métodos
Assert::equal()
e Assert::notEqual()
, que podem ser usados para descrever facilmente a estrutura.
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'));
Com Expect
, podemos fazer quase as mesmas afirmações que com Assert
. Portanto, temos métodos como
Expect::same()
, Expect::match()
, Expect::count()
, etc. Além disso, podemos
encadeá-los como:
Expect::type(MyIterator::class)->andCount(5); # we expect MyIterator and items count is 5
Ou, podemos escrever os próprios responsáveis pelas asserções.
Expect::that(function ($value) {
# return false if expectation fails
});
Investigação de Assertions Failed
O Tester mostra onde está o erro quando uma asserção falha. Quando comparamos estruturas complexas, o Tester cria
despejos de valores comparados e os salva no diretório output
. Por exemplo, quando o teste imaginário
Arrays.recursive.phpt
falha, os lixões serão salvos da seguinte forma:
app/
└── tests/
├── output/
│ ├── Arrays.recursive.actual # actual value
│ └── Arrays.recursive.expected # expected value
│
└── Arrays.recursive.phpt # failing test
Podemos mudar o nome do diretório por Tester\Dumper::$dumpDir
.