1Cの単体テスト、BDD、および流動性ステートメントのパワー(流assertなアサーション)

ちょっとした歴史



上品な男のケント・ベックのおかげで、素晴らしいテスト駆動開発手法が生まれました。 コードを書くという通常のプロセスを逆さまにするという珍しいアプローチ(機能テストは実装前に作成されます)にもかかわらず、テストによる開発が事実上の標準になったとすでに言えます。 ほとんどすべての空席には、TDD方法論と関連ツールを使用した知識と経験が必要です。 なぜ、思考の習慣的なパラダイムを打破する方法論が定着し、標準化されたように見えるのでしょうか? 通常のパラダイムで書かれたコードは通常完全にテストに適さないため、「寿命は手動テストには短すぎ」、既存のコードの自動テストを書くことができない場合があるためです。



この方法論は、その存在中にBDDの形でフォークを獲得できたことに注目する価値があります。 Dan Northは、彼の記事( Introducing BDD )で、開発者間でTDDを実装することの難しさを指摘し、これらの問題を解決するための行動駆動開発と呼ばれるプラクティスを提案しました。 BDDの主な機能は、TDDとDDDの混合と呼ぶことができ、最初はテストメソッドの適切な命名で表されていました(テストメソッドの名前は文である必要があります)。 現時点では、BDDの遠地点は、ガーキン言語とそれを使用するツール(Cucumber、RSpecなど)の誕生と考えることができます。



私は何に導かれ、1Cはそれと何の関係がありますか?



1Cの世界では、TDDが人気を博し始めています。 TDDの知識を要求する1C開発者の空きをまだ見ていません。 重要な障害は、1Cプラットフォームカーネルのコードの前にテストを作成するためのツールがないことです。

それでは、現在、1Cの世界でのテストによる開発のために何がありますか?



そして今、社会の自尊心のあるメンバーに発生するはずの質問:「どうすれば個人的に支援できますか?(私の場合、1C開発の世界に進んで高度な方法論に切り替えることができますか?」)。



この質問に答える前に、テストでよく書かれたステートメントのトピックに触れたいと思います。 ステートメントは、コードの予想される動作を示しています。 声明を一目見れば、テストがどのような動作を伝えようとしているのかを理解するのに十分なはずです。 残念ながら、古典的な声明ではこれを達成することはできません。 多くの場合、長い間読んで、テストの著者の考えを解読する必要があります。

幸いなことに、最近、流なインターフェイスを使用する傾向があり、コードの可視性と直感性に非常に良い影響を与えています。 また、テストツールも無視されず、BDDスタイルのステートメントとも呼ばれる流動的なステートメントがありました。 より自然で、便利で、表現力豊かな方法でステートメントを作成できます。

初めて、 制約ベースのアサートモデルの NUnitで同様のアプローチに出会いました。

その後、たくさんのmocha.js + chai.jsに出会いましたが、これは非常に熱心でした。



それで、「1C開発の世界が高度な方法論に切り替わるのを個人的にどのように支援できますか?」という質問に対する私の答えは-初心者向けの流動的な声明です。



1Cプラットフォーム用の流動的なステートメントの開発



テストによる実世界の開発者として、私はテストから開発を始めました。 最初のテストメソッドには1行のみが含まれていました。



.(5).(5);
      
      





実装は驚くほど簡単でした。 Expect変数には外部処理オブジェクト(以降、承認オブジェクトと呼びます)が含まれ、このオブジェクトにはエクスポートメソッドがあります。



各メソッドは同じクレームオブジェクトを返します。



次のステップは、オプションのパラメーターMessageで拡張されたWhatメソッドの署名です。これにより、ステートメントによってスローされる例外がより有益になります。



さらに、私は不正確なステートメントをどうするかについて考えました。 そのような声明があるべきですか? 古典的な声明では、ほとんどすべての声明には独自の対抗策があります(等しい/等しくない、満たされた/満たされていないなど)。 しかし、流動的な声明ではありません! したがって、テスト番号2が生まれました。



 .(5)..(7);
      
      





きれいに見えますが、1Cでは実現できません。 別の試み:



 .(5).().(7);
      
      





まだ美しく、一見実現可能です。 承認オブジェクトのコンテキストで否定フラグを設定し、チェーン内の次のステートメントをこのフラグと照合するだけです。 本質的に、XORが必要でしたが、1C言語では次のようになります。



  =  <> ;
      
      





しかし、プラットフォームはHe()メソッドでオブジェクトをコンパイルすることを拒否しました。 実際には、 Notは予約語であり、その使用の制限は メソッドの名前で。 同僚とのブレーンストーミングでは、この問題をうまく回避することができなかったため、否定のある最終バージョンは次のようになります。



 .(5)._().(7);
      
      





誰かが問題に対するより良い解決策を提供してくれたら、私はそれを大いに感謝します。 ロシア語の文字をラテンアルファベットに置き換えるオプションを提供しないでください!



その結果、次のAPIが誕生しました



What(チェック済み値、メッセージ= "") -チェック済み値と、外部処理のコンテキストでステートメントによってスローされた例外の追加メッセージを格納します。



Not_() -チェーンに続くステートメントを拒否します。



これは真実です() -テストされる値は真実であると述べています。



これはFalse() -チェック対象の値がFalseであると主張します。



Equals(ExpectedValue) -チェックされる値が期待値と等しいと主張します。



大きい(小さい値) -チェックされる値がステートメントに渡される値より大きいと主張します。



より大きいか等しい(より小さいまたは等しい値)/最小(最小 -チェックされる値がステートメントに渡された値以上であると主張します。



より小さいか等しい(より大きいまたは等しい値)/最大(最大 -チェックされる値がステートメントに渡された値以下であることを主張します。



Less(より大きい値) -チェックされる値がステートメントに渡される値より小さいと主張します。



Filled() -チェックされた値が同じタイプのデフォルト値と異なると主張します。



()があります-チェックされた値がNullおよびNot Undefinedではないことを主張します。



This Undefined() -チェックされる値が未定義であると主張します。



これはNull() -チェック対象の値がNullであると主張します。



HasType(Type) -チェックされた値がステートメントに渡されたタイプまたはタイプ名を持っていると主張します。



Between(StartValue、EndValue) -チェックされた値がステートメントに渡された値の間にあると主張します。



含む(SearchedValue) -チェックされた値に、渡されたステートメントが含まれていると主張します。 文字列とコレクションに適用されます。



HasLength(ExpectedLength) -チェックされる値の長さがステートメントに渡されることを示します。 文字列とコレクションに適用されます。



使用例



 .(1 > 0).(); .(13 = 2)._().(); .(5 = 7).(); .(5).(5); .(4).(2); .(7).(7); .(.()).(9); .(90).(100); .(()).(90); .(55).(56); .(1).(); .( ).(); .().(); .(.).Null(); .("").(""); .(7).(1, 10); .(" ").(""); .(" ").(12);
      
      





例はもう少し複雑です:



 .(" ") .() ._().("") .(12) ._().("!!!");
      
      





あとがき



開発はgithubで利用可能です。 探究心のある読者は気付いているに違いないが、リンクは単なる文のライブラリ以上のものにつながる。 しかし、これはすでに次の記事で重要です。



All Articles