在 Let’s Encrypt 的 Tiwtter 看到「ACME v2 and Wildcard Certificate Support is Live」,已經開放大家申請 wildcard 的憑證:
另外自己在更新 certification 的 dehydrated 已經開始支援,先來看一下怎麼玩,如果要用的話就來裝 gslin 打包的 PPA。
軟體開發、伺服器和生活瑣事
在 Let’s Encrypt 的 Tiwtter 看到「ACME v2 and Wildcard Certificate Support is Live」,已經開放大家申請 wildcard 的憑證:
另外自己在更新 certification 的 dehydrated 已經開始支援,先來看一下怎麼玩,如果要用的話就來裝 gslin 打包的 PPA。
看了 PHPUnit 的 source code,發現有個很有趣的寫法:
function assertSame($expected, $actual, string $message = ''): void
{
Assert::assertSame(...func_get_args());
}
最初以為「…」只能用在定義 variable-length function argument/param,重新看了文件才發現之前文件沒有看完,也可以拿來把陣列分別當作 argument/param 傳入:
function add($a, $b) {
return $a + $b;
}
add(...[1, 2]); // $a = 1, $b = 2
// or ...
$args = [1, 2];
add(...$args);
複習 PHPUnit 順手寫了小程式做實驗。
PHPUnit 為了讓各個不同的 test case 不會因為 super globals 變數而互相影響,設計了 「backupGlobals」這個功能。先來看範例程式:
class MyTest extends TestCase
{
public function testOne()
{
$GLOBALS['test'] = 123;
$this->assertArrayHasKey('test', $GLOBALS);
}
public function testTwo()
{
$this->assertArrayHasKey('test', $GLOBALS);
}
}
範例中 testOne() 修改了 $GLOBALS 變數的內容,如果在不使用「backupGlobals」的情況下,在 testTwo() 中的 $GLOBALS 也會保留 testOne() 修改過的內容,使 testTow() 抓得到「test」這個 key:
$ phpunit MyTest.php
PHPUnit 7.0.2 by Sebastian Bergmann and contributors.
.. 2 / 2 (100%)
Time: 40 ms, Memory: 4.00MB
OK (2 tests, 2 assertions)
也就表示 testOne() 影響到了 testTwo() 的測試結果,這在測試時是不樂見的,各個測試應該有獨立的測試環境,不應該互相影響。
使用「backupGlobals」功能,PHPUnit 會在 test case 執行之前,使用 serialize() 對 super globals 做備份,並在測試結束以後 unserialize() 復原,所以 testOne() 中做的修改就不會影響到 testTwo() 了:
$ phpunit --globals-backup MyTest.php
PHPUnit 7.0.2 by Sebastian Bergmann and contributors.
.F 2 / 2 (100%)
Time: 52 ms, Memory: 4.00MB
There was 1 failure:
1) MyTest::testTwo
Failed asserting that an array has the key 'test'.
/home/johnroyer/tmp/MyTest.php:16
FAILURES!
Tests: 2, Assertions: 2, Failures: 1.
重點來了,因為是使用 serialize() 和 unserialize(),所以只能針對 primitive type 進行備份和還原,如果使用了 object 或是 singleton 時,「backupGlobals」就派不上用場了。這個時候要使用殺手鐧「runTestsInSeparateProcesses」:
/**
* @runTestsInSeparateProcesses
*/
class MyTest extends TestCase
{
....
}
使用這個 annotation 會讓 PHPUnit 為每個 test case 分別 fork 出新的 proccess 進行測試,因此不同 test case 就可以在完全獨立的環境下執行不受影響:
$ phpunit MyTest.php
PHPUnit 7.0.2 by Sebastian Bergmann and contributors.
.F 2 / 2 (100%)
Time: 303 ms, Memory: 4.00MB
There was 1 failure:
1) MyTest::testTwo
Failed asserting that an array has the key 'test'.
/home/johnroyer/tmp/MyTest.php:19
FAILURES!
Tests: 2, Assertions: 2, Failures: 1.
但使用這個殺手鐧也是要付出一點代價:時間。最前二次執行 PHPUnit 時,跑完二個 test case 只花費了 50ms 左右,而開 proccess 來進行測試則花了 300ms。
前幾天看到國外有人使用 PHP 7.x 和 HHVM 做了效能測試「The Definitive PHP 5.6, 7.0, 7.1, 7.2 & HHVM Benchmarks (2018)」,可以從比較上看到 PHP 7 以後速度有大幅的躍進,到了 7.1 與 7.2 已經和 HHVM 不相上下了。
目前用過跑起來最慢的 project 應該是 Gallery 和 Druple (古早的版本),由上圖可以看到 PHP 7.x 幾乎快了 5.x 一倍,另外在 7.1 的效能也逼近 HHVM 了。
相較於 HHVM 在佈署之前還要經過編譯步驟,我想應該很多人會回來使用 PHP 7.x 吧。