16

最近、JavaScript ミニフィケーション ライブラリの新しいビルドにアップグレードしました。

テストチームによる大量の品質保証作業の後、新しいバージョンのミニファイアーには、コードブロックの背後にある意図と意味を変更する問題があることが発見されました。

(人生の教訓: 新しいバージョンが必要だと本当に確信していない限り、JS ミニファイヤーをアップグレードしないでください。)

ミニファイヤは、「ビジネス ロジック」ほどではなく、DOM 関連のアクティビティに重点を置いたクライアント側の JavaScript コードに使用されます。

ミニファイヤのアップグレードによって壊れたものの簡単な例:

function process(count)
{
     var value = ""; 
     value += count; //1. Two consecutive += statements
     value += count;
     count++;        //2. Some other statement
     return value;   //3. Return
}

次のように誤って縮小されました:

function process(n){var t="";return t+n+n,n++,t}

JavaScript が DOM インタラクション (データ入力など) に重きを置いていることを考えると、いくつかの問題を潜在的にキャッチするためにいくつかの単体テストを作成することはできますが、ユーザー テスト (自動化されていない) なしで完全にテストすることは非常に困難です。Esprima のような JS から AST へのライブラリを使用することを検討しましたが、縮小されたコードに加えることができる変更の性質を考えると、あまりにも多くの誤検出が発生することになります。

また、代表的なテストを作成することも検討しましたが、それは終わりのない作業のようです (そして、ケースを見逃す可能性があります)。

参考までに: これは、数十万行の JavaScript コードを含む非常に洗練された Web アプリケーションです。

私たちは、「すべてをもう一度徹底的にテストし、繰り返す」のではなく、縮小プロセスをテストするための方法論を探しています。プロセスにもう少し厳密さ/科学を適用したいと考えています。

理想的には、テストのためのより優れた科学的方法があれば、それぞれが新しい微妙な方法でコードを壊すことを恐れずに、複数のミニファイヤを試すことができます。

アップデート:

私たちが持っていたアイデアの1つは、次のことでした。

  1. 古いバージョンで縮小する
  2. 美化する
  3. 新しいバージョンで縮小し、
  4. 美化し、そして
  5. 視覚的に違います。

良いアイデアのように思えましたが、違いがあまりにも一般的だったため、diff ツールはほぼすべての行に違いがあるとフラグを立てました。

4

6 に答える 6

1

QUnitjsなどの単体テスト フレームワークを検討しましたか? 単体テストを作成するのはかなりの労力を要しますが、最終的には繰り返し可能なテスト手順が得られます。

于 2013-02-13T16:51:06.113 に答える
1

CI (継続的インテグレーション環境) 内で自動化された単体テストの使用を開始する必要があるように思えます。QUnit はあちこちに散らばっていますが、実際には QUnit は非常に脆弱なテスト システムであり、そのアサーションは最低限必要最低限​​のものです (適切なアサーション ベースの構文を実際に使用することさえありません)。TDD としての資格はわずかであり、BDD もうまく処理できません。

個人的には、 JasmineJsTestDriver (他の UT フレームワークまたは独自のフレームワークを使用でき、信じられないほど高速です... ただし、修正してほしい安定性の問題がいくつかあります) を使用して Jasmine をお勧めします。多重比較による縮小プロセス。

いくつかの比較は、おそらく次のようにする必要があります。

  • 元のコードとその機能は期待どおりに動作します
  • 縮小されたコードと比較して (これが BDD の出番です。縮小されたコードでも同じ機能パフォーマンス/結果が期待されます)
  • 私はさらに一歩進んで(縮小アプローチに応じて)、縮小を美化して別の比較を行うテストを行います(これにより、テストがより堅牢になり、有効性がより保証されます)。

これらの種類のテストは、動作と比較とa が true であり、解析後も true である場合だけでなく、機能/動作の前/後の状態。

これらの単体テストのセットアップにはしばらく時間がかかる可能性がありますが、その大規模なコードベースを使用した反復的なアプローチです...最初の重要なチョークポイントまたは脆弱なポイントを迅速かつ早期にテストし、テストをすべてに拡張します (私が常に設定した方法)私のチームは、ユニットテストがない限り、この時点以降は完全でRCとは見なされないということです...ユニットテストがなく、更新/変更/維持する必要がある古いものは、変更時にユニットテストを作成する必要があります。コード カバレッジを増やしながら、テストされていないコードの量をより管理しやすく論理的な方法で常に改善および縮小しています)。

単体テストを CI で起動して実行したら、それらをビルド プロセスに結び付けることができます: 単体テストのないビルドが失敗した場合、または単体テストが失敗したときにアラートを送信したり、チェックインごとに事前に監視したりします。 JSDoc3 などでドキュメントを自動生成します。

あなたが説明している問題は、CIと単体テストが構築された目的であり、より具体的には、そのアプローチはコードベースのサイズの影響を最小限に抑えます...サイズはそれをより複雑にするのではなく、単に期間を長くしますテストが全面的により長く機能するようにします。

次に、それを JSDoc3 と組み合わせると、ほとんどのフロント エンド ショップの 90% よりも優れたスタイルになります。その時点でエンジニアにとって信じられないほど堅牢で便利であり、自己永続的になります。

このトピックについては、本当に延々と続けることができます。どのようにアプローチし、チームを結集させ、自己形成および自己永続化させるかについては、さまざまなニュアンスがあります。最も重要なのは、テスト可能なコードを作成することです。 ..しかし、概念レベルから...単体テストを作成して自動化します。いつも。

あまりにも長い間、フロントエンド開発者は、実際のエンジニアリングの厳密さと規律を適用せずに、中途半端な開発を行ってきました。フロントエンドがますます強力で熱くなるにつれて、それは変わらなければならず、変わりつつあります。十分にテストされ、十分にカバーされ、自動化されたテストとフロントエンド/RIA アプリケーションの継続的統合の概念は、その変化の大きなニーズの 1 つです。

于 2013-02-22T20:16:01.370 に答える
0

さまざまな環境で Web アプリケーションのテストを自動化できるSelenium Web Driverのようなものを見ることができます。複数環境のテストを実行するためのクラウド ホスト型 VM ソリューションがいくつかあるため、Webkit では機能するが IE では機能しない場合に問題が発生することはありません。

于 2013-02-13T16:50:15.990 に答える
0

最小化された JavaScript のデバッグに役立つように、ソース マップの使用を検討する必要があります。ソース マップは、CoffeeScript や私の新しいお気に入りの TypeScript などの JavaScript のスーパーセットでも動作します。

縮小するだけでなく、ソース マップも作成するクロージャ コンパイラを使用します。言うまでもなく、これは最も積極的で、最小のファイルを生成します。最後に、ミニフィケーションで何が起こっているのかを知り、互換性のあるコードを記述する必要があります。サンプル コードではリファクタリングを使用できます。

ソース マップに関するこの記事をチェックしてください: http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/

また、クロージャーコンパイラーのドキュメントもチェックしてください。縮小のためのより良いコードを書く方法に関する提案があります: https://developers.google.com/closure/compiler/

于 2013-02-15T06:01:35.463 に答える
0

コードを縮小して変更する高度なモードでクロージャ コンパイラを使用するため、単体テストもコンパイルするため、コードと一緒にテストを縮小して実行することを検討できます。

于 2013-02-20T18:02:30.317 に答える
0

テスト ソリューションではありませんが、TypeScript に切り替えて、あなたのような大規模な JS アプリを作成するのはどうですか?

TypeScript とそのデフォルトの最小エンジンでテストしたところ、正常に動作しました。

countあなたの引数が数値であると仮定します。

タイプ スクリプトは次のようになります。

class ProcessorX {
    ProcessX(count: number): string {
        var value = '';
        value += count.toString();
        value += count.toString();
        count++;
        return value;
    }
}

次のようなjsを生成します。

var ProcessorX = (function () {
    function ProcessorX() { }
    ProcessorX.prototype.ProcessX = function (count) {
        var value = '';
        value += count.toString();
        value += count.toString();
        count++;
        return value;
    };
    return ProcessorX;
})();

次に、次のように縮小します。

var ProcessorX=function(){function n(){}return n.prototype.ProcessX=function(n){var t="";return t+=n.toString(),t+=n.toString(),n++,t},n}()

jsfiddleにあります。

あなたcountが の場合string、このfiddle .

于 2013-02-20T17:43:08.997 に答える