Introdução
Laravel é um framework PHP bacana, usamos o tempo todo na empresa. Mas como você sabe, nada no mundo é perfeito, você sempre pode sugerir melhorias.
Algumas semanas atrás eu tentei fazer uma pequena melhoria na área de teste do Laravel, abri duas solicitações de pull ( # 1 e # 2 ). Ambas as solicitações pull foram rejeitadas pelo autor do framework, Taylor, mas no final, no mesmo dia, ele publicou sua própria implementação da mesma funcionalidade, da qual ele até se gabou no Twitter. E, oh deuses, a compreensão é terrível!
Contexto
Preferimos o teste de integração por conta própria, pois permite que você alcance um bom equilíbrio entre o custo do teste automatizado e a confiança em suas implantações. Freqüentemente, em nossos testes de integração, fazemos algo em nome do usuário e, em seguida, queremos ter certeza de que o usuário eventualmente recebeu algum tipo de carta. Para fazer isso, o Laravel implementa a forma padrão:
<?php
public function test_orders_can_be_shipped()
{
Mail::fake();
Mail::assertSent(OrderShipped::class);
}
, , , - , ? , " - ", " - ".
Laravel , :
<?php
Mail::assertSent(OrderShipped::class, function ($mail) use ($user) {
return $mail->hasTo($user->email) &&
$mail->somePublicProperty == 'someValue';
});
, - To/Cc/Bcc (, , ). Mailable Laravel , . render() Mailable, :
<?php
public function render()
{
return $this->withLocale($this->locale, function () {
Container::getInstance()->call([$this, 'build']);
return Container::getInstance()->make('mailer')->render(
$this->buildView(), $this->buildViewData()
);
});
}
render(), . , buildView() buildViewData() - .
, :
Mailable, . . .
Mailable Macroable, . , Mailable , "with", Macroable . .
- -, proxy, Mailable, , , , - seeInHtml(), seeInText(). .
( -) Mockery, Mailable , :
<?php
public function email_confirmation_is_correct()
{
Mail::fake();
event(new TestEvent());
config(['app.name' => 'Test App']);
Mail::assertSent(TestMail::class, function (TestMail $mail) {
return $mail->hasTo('test@test.com')
&& $mail->seeInHtml('shipped')
&& $mail->dontSeeInHtml('failed')
&& $mail->seeInText('Test App');
});
}
, API - Laravel, - , ( MailFake, TestMailable). production- .
, , - - :
, , - , , , , - ! API , "assert".
– , , .
– , , , . , – .
production- Mailable, , . , , .
, , Mailable:
<?php
/**
* @param string $string
* @return void
*/
public function assertSeeInText($string)
{
[$html, $text] = $this->renderForAssertions();
PHPUnit::assertTrue(
Str::contains($text, $string),
"Did not see expected text [{$string}] within text email body."
);
}
:
Laravel, production-, . , - . , - MailFake, - Mailable
Mailable PHPUnit, development-only, composer.json. , production-
:
[$html, $text] = $this->renderForAssertions();
, , . , , , .
Nosso objetivo era testar o código de combate - métodos render () e send (). Testamos um novo método recém-criado que ninguém usará na prática.
Vamos dar uma olhada neste método:
<?php
protected function renderForAssertions()
{
if ($this->assertionableRenderStrings) {
return $this->assertionableRenderStrings;
}
return $this->assertionableRenderStrings = $this->withLocale($this->locale, function () {
Container::getInstance()->call([$this, 'build']);
$html = Container::getInstance()->make('mailer')->render(
$view = $this->buildView(), $this->buildViewData()
);
$text = $view['text'] ?? '';
if (! empty($text) && ! $text instanceof Htmlable) {
$text = Container::getInstance()->make('mailer')->render(
$view['text'], $this->buildViewData()
);
}
return [(string) $html, (string) $text];
});
}
Oh, não é um método, mas um monstro!
Não apenas é muito difícil de ler, mas também repete muitas linhas do método render (), então agora existe uma chance de que algum dia os métodos irão divergir. E toda vez que você edita render (), agora você precisa se lembrar de corrigir renderForAssertions ().
Em minha opinião, é fundamentalmente errado testar métodos especialmente projetados para testes, em vez de código real. Isso é algum tipo de bobagem.
Acho que com este commit meu framework favorito ficou um pouco pior :(