ソースモデルの単体テスト


10

私のカスタム拡張機能には、エンティティの追加/編集フォームの一部の選択または複数選択、あるいはその両方の目的を満たすだけのモデルがいくつかあります。
したがって、これらはmagentoが「ソースモデル」と呼ぶものです。
関連する値は常に同じであり、メソッドは同じものを返します。
それらを単体テストするにはどうすればよいですか?または、さらに良いことに、それらの単体テストを作成する必要がありますか?
例を示します。
次のクラスは、呼び出されたフィールドの追加/編集フォーム、typeおよび同じフィールドのグリッド列に使用されます。

<?php
namespace Sample\News\Model\Author\Source;

use Magento\Framework\Option\ArrayInterface;

class Type implements ArrayInterface
{
    const COLLABORATOR = 1;
    const EMPLOYEE = 2;

    /**
     * Get options
     *
     * @return array
     */
    public function toOptionArray()
    {
        $_options = [
            [
                'value' => '',
                'label' => ''
            ],
            [
                'value' => self::COLLABORATOR,
                'label' => __('Collaborator')
            ],
            [
                'value' => self::EMPLOYEE,
                'label' => __('Employee')
            ],
        ];
        return $_options;
    }

    /**
     * get options as key value pair
     *
     * @return array
     */
    public function getOptions()
    {
        $_tmpOptions = $this->toOptionArray();
        $_options = [];
        foreach ($_tmpOptions as $option) {
            $_options[$option['value']] = $option['label'];
        }
        return $_options;
    }
}

回答:


15

これは素晴らしいスレッドで、@ KAndyと@fschmenglerの両方の回答が大好きです。
「Xをテストすべきか?」などの質問をするときに価値があると思う追加の考えを追加したいと思います。または「Xをテストするにはどうすればよいですか?」

何がうまくいかないのでしょうか?

  • 私はばかげたタイプミスをすることができました(いつも起こります)
    これは通常テストを書くことを正当化しません。
  • 必要なコードをコアまたは別のモジュールからコピーして、必要に応じて調整しますか?
    これは実際には非常に危険なことであり、微妙なバグを残すことがよくあります。この場合、テストが高すぎない場合は、テストを作成することをお勧めします。ソースモデルを構成に基づいて実際に作成すると、より危険なIMOになります。
  • 別のモジュールと競合する可能性はありますか?
    これはほとんど構成コードにのみ適用されます。そのような場合、いつそれが起こったのかを教えてくれる統合テストが欲しいです。
  • Magentoは将来のリリースでAPIを変更する可能性がありますか?
    この場合、コードはインターフェイスにのみ依存しているため、ほとんどありません。しかし、より具体的なクラスが含まれている場合、またはコードがコアクラスを拡張している場合、これは潜在的なリスクになります。
  • 新しいバージョンのPHPでコードが壊れる可能性があります。あるいは、私は今後何年もPHP 5.6をサポートしたいと考えています。
    繰り返しになりますが、ここではほとんどありませんが、将来、互換性のない構文を使用するようにコードを変更する必要がある場合は、テストで警告を表示する必要があります。

コードのテストにはどれくらいの費用がかかりますか?

これには2つの側面があります。

  • テストを書くのにかかる労力と時間
  • これから手動で作成するコードをテストするのにかかる労力と時間。

一部のコードの開発中、私は自分が書いているコードを、実行が完了するまでかなり頻繁に実行しなければならない傾向があります。これはもちろん単体テストを使用するとはるかに簡単です。

あなたの場合、テストを書くのはとても安いです。時間も手間もかかりません。@KAndyは、すべてのコードを維持する必要があることは正しいですが、すべてのテストを維持する必要はありません。
これは、ユニットテストを作成する例である場合があります。これは、私がおかしな間違いを犯していないことを確認し、クラスが終了したらそれを削除するためのものです。テストが長期的な価値を提供しない場合、それらを削除することは理にかなっていると思います。

この質問は、作成するテストのタイプ(ユニットまたは統合など)を選択する上でも重要です。

私が書いているコードはどれほど価値がありますか?

私が書いているコードの一部がモジュールが提供するサービスに不可欠である場合、それがどんなに些細なことでも、私はそれをテストします。
それが、たとえばUIに焦点を当てた、ビジネスロジックの一部ではない、ほんの少しのユーティリティメソッドである場合は、おそらくそうではありません。

コードを変更する必要がありますか?

時間が経つにつれ、テストカバレッジに慣れてきましたが、カバーされていないコードの変更は非常に不安に感じられます。これには、ソースモデルにオプションを追加するような単純なものだけでなく、クラスを別のフォルダー/名前空間に移動したり、メソッドの名前を変更したりすることも含まれます。
このような変更をテストすることは非常に重要です。

書類は必要ですか?

コードを使用するのはどれくらい難しいですか?あなたの例ではそれは取るに足らないことですが、いくつかのより複雑なケースでは、テストがあることは他の開発者(または私自身が数か月で)の文書化の目的に最適です。

探索と学習

一部のコードで作業していて、それをテストする方法がわからない場合、テストを作成することは非常に貴重です。このプロセスにより、ほとんどの場合、自分が何を扱っているかをより深く理解できます。
これは、まだテストを学んでいると考える開発者に特に当てはまります。
これは、提供する主な値が学習であったため、後でテストを削除することが理にかなっている可能性がある例でもあります。

規律とストレス

red-green-refactorループに固執することは、私が速く進むのに役立ちます。これは特に圧力下で当てはまります。そのため、一部のコードが実際にテストに値しない場合でも、特にコードが簡単にテストできる場合は、TDDに従う可能性があります。
これは私を流れと警戒心に保ちます。

何をどのようにテストしますか?

また、非常に異なる粒度でテストを作成できることも考慮してください。

  • 正確な戻り値をテストします。
    これは非常に厳格なテストであり、すべての変更に合わせて調整する必要があります。たとえば、戻り配列の項目の順序が変更された場合、テストを中断しますか?
  • 戻り値の構造をテストします。
    ソースモデルの場合、これは各サブ配列を2つのレコードとしてチェックし、1つはaでlabel、もう1つはvalueキーでチェックします。
  • クラスの実装を確認しますArrayInterface
  • クラスをテストするgetOptions()と、実装されたインターフェースの一部ではないメソッドが提供されます。

テストできる可能性のあるものごとに、価値、保守性、およびコストを検討します。

概要

要約すると、コードの一部をテストする必要があるかどうかについて、質問に対する真の答えは1つではありません。状況に応じて、開発者ごとに答えは異なります。


2
正解です。「価値がなくなったときにテストを削除する」部分を強調したいと思います。初期の開発者を支援していた古いテストが、長期的に邪魔になる場合があります。
Fabian Schmengler、2016

1
あなたは私が疑っていた他の2つの質問に答えました。ありがとう
マリウス

6

私の意見では、「ソースモデルの単体テストを作成する、はいまたはいいえ」に対する一般的な答えはありません。

私はソースモデルの単体テストを作成しましたが、それらは外部データをフェッチする動的ソースモデルであり、それは完全に理にかなっています。

(例のように)美化された配列にすぎないソースモデルの場合、ユニットテストを作成する必要はありません。しかし、ある意味では、間違いを犯していないことを確認する必要があります。いくつかのオプションがあります:

  1. 単体テスト
  2. 統合テスト
  3. 手動で構成を確認する

TDDをフォローしていますか?次に、(1)と(2)の間、または両方を選択します。それ以外の場合は、(2)と(3)の間で選択します。


システム構成オプションのソースモデルを使用する場合、統合テスト(すべての構成オプションに対して1つのテスト)が構成セクションをレンダリングし、<select>要素が存在し、期待される値が含まれているかどうかを確認できます。これは特定の1つのクラスをテストすることではなく、すべてが正しく結び付けられていることをテストすることです。


そして、@ KAndyが言ったように、理想的にはそれほど多くのボイラープレートは必要なく、すでにユニットテストされている基本クラスを拡張し、プロパティをオーバーライドするか、外部設定で値を定義するだけです。

そのシナリオでは、具体的な実装の単体テストは追加の値を提供しません。これらのクラスが多数ある場合はArraySource、Magentoが提供しない限り、自分で基本クラスを作成することをお勧めします。


このような基本クラスを使用すると、ソースモデルは次のようになります。

class Type extends ArraySource
{
    const COLLABORATOR = 1;
    const EMPLOYEE = 2;
    protected $elements = [
        self::COLLABORATOR => 'Collaborator',
        self::EMPLOYEE     => 'Employee',
    ];
    protected $withEmpty = true;
    protected $translate = true;
}

確認していただきありがとうございます。私は栄光のある配列を構成可能なオプションリストに変えようとしますが、正確にN個のオプションを持つモデルにも同じことが当てはまりますか?「ステータス」ソースモデルのようです。
マリウス

「ステータス」ソースモデルが「作成者タイプ」の例とどのように異なるかわかりません
Fabian Schmengler

たとえば、有効なエンティティをフィルタリングするために、フロントエンドで(クラス定数として)値0および1を使用する可能性があるためです。つまり、この場合、オプション値の背後にロジックがあります。key=>valueペアではありません。
マリウス

しかし、このロジックはソースモデルの一部ではありませんよね?つまり、ここでは問題ではありません。他の場所で使用する定数はまだあります。私はそのような含意をどのように使用するかの例を追加しました。
Fabian Schmengler 2016

5

それらを単体テストするにはどうすればよいですか?

私はあなたがすべきではないと思います。

システムにコードを追加すると、サポートとメンテナンスのコストが増加しますが、テストプロセスは無駄がないはずです。

このコード以上のものは存在すべきではありません。Magentoよりも、さまざまな場所で使用するオプションのセットを定義するための1つの一般的な宣言的な方法であるべきだと思います。そして、このクラスのテストを書くことに抵抗があると、悪いコードの匂いがします


1
ありがとう。つまり、これらのオプションはハードコーディングするのではなく、構成ファイル(di.xmlなど)から取得する必要があるということです。私はそれを行うことができます。しかし、ステータスソースモデルについても同じですか?つまり、上記と同じクラスでステータスが有効および無効(1,0)の場合のみ、同じ構成アプローチを使用する必要がありますか?もしそうなら、私はそれが私にとってオーバーエンジニアリングのように繋がっていると言いたいです。
マリウス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.