pengantar
Laravel adalah kerangka kerja PHP yang keren, kami menggunakannya sepanjang waktu di perusahaan. Tetapi seperti yang Anda ketahui, tidak ada yang sempurna di dunia ini, Anda selalu dapat menyarankan perbaikan.
Beberapa minggu yang lalu saya mencoba membuat satu perbaikan kecil di area uji Laravel, membuka dua permintaan tarik ( # 1 dan # 2 ). Kedua permintaan tarik tersebut ditolak oleh penulis kerangka kerja, Taylor, tetapi pada akhirnya dia sendiri menerbitkan penerapannya sendiri untuk fungsi yang sama pada hari yang sama, yang bahkan dia banggakan di Twitter. Dan, oh tuhan, realisasinya mengerikan!
Konteks
Kami lebih suka pengujian integrasi sendiri, karena ini memungkinkan Anda mencapai keseimbangan yang baik antara biaya pengujian otomatis dan keyakinan dalam penerapan Anda. Seringkali, dalam pengujian integrasi, kami melakukan sesuatu atas nama pengguna, lalu kami ingin memastikan bahwa pengguna pada akhirnya menerima semacam surat. Untuk melakukan ini, Laravel menerapkan cara standar:
<?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();
, , . , , , .
Tujuan kami adalah untuk menguji metode kode pertempuran - render () dan send (). Kami menguji metode baru yang baru dibuat, yang tidak akan digunakan oleh siapa pun dalam praktiknya.
Mari kita lihat metode ini:
<?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, bukan metode, tapi monster!
Tidak hanya sangat sulit untuk dibaca, ia juga mengulang banyak baris dari metode render (), jadi sekarang ada kemungkinan bahwa suatu saat metode tersebut akan menyimpang. Dan setiap kali Anda mengedit render (), sekarang Anda harus ingat untuk memperbaiki renderForAssertions ().
Menurut pendapat saya, pada dasarnya salah untuk menguji metode yang dirancang khusus untuk pengujian, alih-alih kode nyata. Ini semacam omong kosong.
Saya menemukan bahwa dengan komit ini, kerangka kerja favorit saya menjadi sedikit lebih buruk :(