苦痛と恐れのない継承をテストする方法

画像



d + 20歳のプロジェクトを取得した、または来ましたか? PHPコードはマンモスの狩猟の間に書かれたので、軽く読まないのですか? あなたは少なくともそれを保存する必要があり、最大で-リファクタリングまたは書き換えますか?



これらの質問の後で、すぐに呼吸や脈拍がなかった場合は、この記事はすでにそのようないじめの犠牲者であるか、そのような運命の変化を予測している人を対象としています。



これは、この状況に典型的な特定のタスクの1つです。リファクタリングまたは変更の前に、ユニットをレガシーコードテストでカバーします。 つまり、関数やメソッドのスタブの作成(滴下、シミュレーションなど)をその場で実行します。



私の場合、主な問題である次の2つのソリューションを提供したいと思います。



1.スタブ関数のシーケンシャルリターン



public function getSomething($param1, $param2) { $result1 = mysql_query('SELECT * FROM table1'); // ... if ($result1['field'] == $param1) { $result2 = mysql_query('SELECT * FROM table2'); } // ... if ($result2['field'] == $param2) { $result3 = mysql_query('SELECT * FROM table3'); } // ... return isset($result3) ? $result3 : $result2; }
      
      





このようなコードをテストでカバーするには、いくつかのオプションがあります。





2.テストされた機能に影響を与えないコードの実行



 public function sendSomething(array $data) { $ch = curl_init(); $result = mysql_query('SELECT url FROM info WHERE id = ' . $data['someId']); curl_setopt($ch, CURLOPT_URL, $result['url']); curl_setopt($ch, CURLOPT_POSTFIELDS, implode('&', $data); // ... curl_exec($ch); } public function myMethod() { $data = SomeCLass::getSomeData(); // ... $data = OtherClass::modifyData($data); // ... //  - ,     $data // ... $this->sendSomething($data); // ... return $completelyOtherVariable; }
      
      





オプション:





これらの例は主に「遠いところにある」ものですが、少なくとも私の実務ではある程度の類似性があります。 はい、より明確に。



ほとんどの場合、両方の場合でオプション#3を選択すると、これらすべてが最も簡単にパスします。 使用するもの、 runkitまたはwopzを決定する必要がありますか? 私にとって、答えは明白です。なぜなら、文字列にphpコードを記述して、それをパラメーターとして渡すのは、倒錯だからです。



使用するがネイティブではない主な機能:



 void uopz_function ( string $class , string $function , Closure $handler [, int $modifiers ] )
      
      





彼女はとてもシンプルです。 これらの関数を報告します。これらの関数を再定義し、元の関数の代わりに実行される匿名関数を渡します。 そこにある関数のスコープを「再生」することもできますが、現在はそれについてではありません。



中間者+プログラマーは、次に何をすべきかをおおまかに把握しているので、これでやめることができますが、ジュニアは自殺の可能性が高いため、そのようなタスクをほとんど任せられません。

この記事は、囚人の作業をわずかにスピードアップし、彼のコードをもう少し読みやすく、短くすることのみを目的としています。



したがって、2つのことを提供したいと思います。



  1. トピックに関する聖戦:「どこで、どのように、いつ形質を正しく使用するか」。
  2. いくつかの便利なメソッドが実装されているuopzの特性ラッパー


すべてのコードを複製するのではなく、ここにgithubへリンクを残しください。 また、便宜上、彼のメソッドを簡単にリストします。



 uopzFlags($function, $flags); //   uopzRedefine($constant, $value); //   uopzFunction($function, Closure $closure, $backup = false); //  "" uopz_function   ,   backup-      : 'mysql_query'  ['ClassName', 'methodName'] uopzMuteFunction($function, $backup = false); //    -, ,    ,  -     ,  curl  "" url, etc uopzRestore($function); //    backup- uopzBackup($function); // backup / (    ) uopzFunctionSimpleReturn($function, $return, $backup = false); //    . return   ,  (  )   . uopzFunctionReplace($function, $replace, $backup = false); //    . uopzFunctionConsistentReturn($function, array $return, $backup = false); //    .    ,     . ,     . uopzFunctionConditionReturn($function, array $conditionList, $default = null, $backup = false); //    .          . uopzFunctionHook($function, Closure $closure, &$return, $backup = false); //       .
      
      





さて、そして実際には、「これ」の助けを借りたこれらの2つの問題の解決策:



1.シーケンシャルリターン



 $this->uopzFunctionConsistentReturn('mysql_query', [ ['id' => 12, 'data' => 'dummy'], ['id' => 31, 'data' => 'dummy'], ['id' => 45, 'data' => 'dummy'], ]); // ,  ,    (  , ): $this->uopzFunctionConditionReturn('mysql_query', [ ['query', 'SELECT * FROM table1', ['id' => 12, 'data' => 'dummy']], ['query', 'SELECT * FROM table2', ['id' => 31, 'data' => 'dummy']], ['query', 'SELECT * FROM table3', ['id' => 45, 'data' => 'dummy']], ]);
      
      





2.傍受の実行



 $this->uopzFunctionHook( ['ClassName', 'sendSomething'], function() { return $data; }, //     $data //      ,   myMethod   sendSomething  $data );
      
      





時間を大幅に節約できたので、共有することにしました。 誰かがこれも役に立つと思います。 そして、世界では毎日、そのようなコードがますます少なくなり、それが有用になることを願っています:)



ご清聴ありがとうございました。



All Articles