PHPユニットテストを実行する場合、時間遅延を含むコード( Time_nanos Sleepなど)により、テストが遅くなり、CI/CDプロセスの実行時間が増加します。さらに、テスト自体もリアルタイムに依存して、テストの予測可能性と安定性を低下させます。効率を改善し、テストの純度を維持するには、通常、「モック」などの遅延関数が必要です。
この記事では、実際に遅延を導入することなく、PHPでの単体テストでのtime_nanosleep機能の動作をシミュレートする方法について説明します。
サービスクラスがあると想像してみてください。このクラスのメソッドは、 time_nanos Sleepを使用して短い遅延操作を実行します。
class TaskRunner
{
public function runWithDelay(): string
{
time_nanosleep(0, 500000000); // 遅れ 0.5 2番
return 'done';
}
}
メソッドを直接テストすると、テストは半秒間一時停止します。これは、多数のテストシナリオで受け入れられません。 Time_nanos Sleepを「交換」または「再定義」する方法を見つける必要があります。
PHPには機能モック機能が組み込まれていませんが、PHPの関数検索メカニズムを使用できます。名前空間では、グローバル関数と同じ名前の関数を定義する場合、名前空間の関数が最初に呼ばれます。
gitbox \ runtimeなど、ビジネスコードを名前空間にカプセル化します。
namespace Gitbox\Runtime;
function time_nanosleep(int $seconds, int $nanoseconds)
{
// 元の動作:グローバル機能を呼び出します
return \time_nanosleep($seconds, $nanoseconds);
}
class TaskRunner
{
public function runWithDelay(): string
{
time_nanosleep(0, 500000000);
return 'done';
}
}
現在、 TaskRunnerはgitbox \ runtime \ time_nanos Sleepを使用しています。これは、テストでオーバーライドできます。
テストファイルでは、同じ名前空間の下でmocked time_nanosleep機能を定義します。
namespace Gitbox\Runtime;
function time_nanosleep(int $seconds, int $nanoseconds)
{
// 模拟遅れ:何もしません
return true;
}
その後、いつものようにテストできます。
use Gitbox\Runtime\TaskRunner;
use PHPUnit\Framework\TestCase;
class TaskRunnerTest extends TestCase
{
public function testRunWithDelay()
{
$runner = new TaskRunner();
$result = $runner->runWithDelay();
$this->assertEquals('done', $result);
}
}
テスト環境でTime_nanos Sleepをオーバーライドするため、テストに実際の遅延はありません。
もう1つのよりオブジェクト指向の方法は、遅延操作をクラスにカプセル化することであり、タスクエグゼクティアに依存関係を注入することにより、例外を提起する、長期的なブロッキングなどのさまざまな動作をより柔軟にシミュレートできます。
interface SleeperInterface
{
public function sleep(): void;
}
class RealSleeper implements SleeperInterface
{
public function sleep(): void
{
time_nanosleep(0, 500000000);
}
}
class TaskRunner
{
private SleeperInterface $sleeper;
public function __construct(SleeperInterface $sleeper)
{
$this->sleeper = $sleeper;
}
public function runWithDelay(): string
{
$this->sleeper->sleep();
return 'done';
}
}
テストでは、モッククラスを使用できます。
class FakeSleeper implements SleeperInterface
{
public function sleep(): void
{
// アクションを実行しないでください
}
}
使い方:
$sleeper = new FakeSleeper();
$runner = new \Gitbox\Runtime\TaskRunner($sleeper);
$this->assertEquals('done', $runner->runWithDelay());
PHPでは、時間依存関数をテストする最も効率的な方法は、通常、名前空間を介して関数を再定義するか、依存関係噴射を使用することです。 Time_nanos Sleepなどのグローバル機能については、名前空間の書き換え手法を使用し、テストロジックをプロジェクトの制御可能な境界内に保持することをお勧めします。
さらに、インターフェイスと依存関係噴射を使用すると、コードがより柔軟でテスト可能になり、より複雑なシナリオに適しています。
これらの方法により、リアルタイムコストを導入することなく、テストの時間遅延を完全にシミュレートでき、テストの効率と安定性を大幅に改善できます。
関連する実用的な例については、 https://gitbox.netをご覧ください。