「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > ドメインに重点を置いてテストを行います。 PHPUnitの例

ドメインに重点を置いてテストを行います。 PHPUnitの例

2024 年 11 月 3 日に公開
ブラウズ:643

導入

開発者はコードの 100% (またはほぼ 100%) をテストしようとすることがよくあります。どうやら、これがすべてのチームがプロジェクトで達成すべき目標のようですが、私の観点からは、コード全体のうち完全にテストする必要があるのは 1 つの部分だけです: あなたのドメイン。

ドメインは基本的に、プロジェクトが実際に何を行うかを定義するコードの一部です。たとえば、エンティティをデータベースに永続化する場合、ドメインはエンティティをデータベース上に永続化する責任はありませんが、永続化されたデータがビジネス モデルに従って意味があるかどうかを確認します。おそらく、データをデータベースに保存するときに、PHP Doctrine などの外部ライブラリを使用することになるでしょう。このライブラリはすでに完全にテストされているため、その動作をテストする必要はありません。 doctrine に正しいデータを渡せば、問題なくデータベースに保存されます。

次のセクションで示す例は、ドメイン駆動設計がどのように機能するかを示すものではありません。ドメイン駆動設計について詳しく説明している記事がたくさんあります。ドメインを明確に定義して分離すると、テストが簡単になり、アプリケーションの動作に焦点を当てられるようになります。

この例は Symfony 環境上に構築され、PHPUnit ライブラリを使用していますが、このアイデアはどの言語やフレームワークにも有効です。

テストするコード

アプリケーションが、指定された日付の降水確率に関するデータを返す外部 API に接続していると想像してみましょう。返されるデータは次のようになります:


{
   "date" : "2022-12-01",
   "rain_probability" : 0.75
}


次に、これらのデータを取得し、次のマッピングに従って分類する必要があります:

  • 雨の確率 低
  • 雨の確率 ≥ 0.40 && 雨の確率 MEDIUM
  • 降水確率 ≥ 0.75:

そして、次のエンティティで記述されたデータベース テーブルに結果を保存します:


#[ORM\Entity(repositoryClass: RainMeasure::class)]
class RainMeasure {

    #[ORM\Column]
    private string $date;

    #[ORM\Column]
    private float $probability;

    #[ORM\Column(length: 10)]
    private string $label;

    // Getters and setters
    // .......
}


外部 API データを取得し、降水確率に応じてラベルを設定し、データベースに保存するハンドラーを作成しましょう。


class RainMeassureHandler {
    private EntityManagerInterface $em;

    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    public function saveMeasure(array $measureData): void
    {
        if($measureData['rain_probability'] = 0.40 && $measureData['rain_probability'] setDate($measureData['date']);
        $rainMeasure->setProbability($measureData['rain_probability']);
        $rainMeasure->setLabel($label);

        $this->em->persist($rainMeasure);
        $this->em->flush();
    }
}


上記のハンドラーのテストを作成しようとすると、テストしたい動作 (確率値に従ってラベルを設定する) が以下であるため、EntityManagerInterface を注入する必要があることがわかります。結果をデータベースに保存する同じハンドラーに結合されます。モックとスタブを使用して EntityManagerInterface をロードしてみることもできますが、それは必要ですか?明らかに違います。前に述べたように、降雨確率に応じて正しいラベルを取得する、ドメインに属する動作のテストに重点を置く必要があります。

テストしたいデカップリング動作

テストを簡素化するために、テストしたい動作を別のクラスに移動します:


class RainMeasureLabelHandler 
{
    public function getLabelFromProbability(float $prob): string
    {
        if($prob = 0.40 && $prob 

そして、RainMeassureHandler は次のようになります:


class RainMeasureHandler 
{
    private EntityManagerInterface $em;

    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    public function saveMeasure(array $measureData): void
    {
        $rainMeasureLabelHandler = new RainMeasureLabelHandler();
        $label = $rainMeasureLabelHandler->getLabelFromProbability($measureData['rain_probability']);

        $rainMeasure = new RainMeasure();
        $rainMeasure->setDate($measureData['date']);
        $rainMeasure->setProbability($measureData['rain_probability']);
        $rainMeasure->setLabel($label);

        $this->em->persist($rainMeasure);
        $this->em->flush();
    }
}


ここで、RainMeasureLabelHandlerのテストに集中できます。これはドメインの一部であり、外部レイヤーへの依存関係はありません。テストは次のように簡単です:

Focusing your tests on the domain. A PHPUnit example

結論

他の種類のテストも役立つだろうと言いたいです。おそらく、API があり、データベースや必要なその他のリソースを含むテスト環境を使用して入力と出力をテストしたいと考えています。ただし、ドメインを分離して完全にテストすることを忘れないでください。

リリースステートメント この記事は次の場所に転載されています: https://dev.to/icolomina/focusing-your-tests-on-the-domain-a-phpunit-example-c82?1 侵害がある場合は、[email protected] までご連絡ください。それを削除するには
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3