2011-09-12 5 views
5

Lire de manière approfondie sur les divers cadres d'assertion en JavaScript. Existe-t-il un type de bibliothèque/cadre «standard» de facto/le plus courant? En choisissant un - quels points méritent le plus d'être remarqués?Assertions en JavaScript

La seule exigence à laquelle je peux penser est une surcharge quasi-nulle en mode production.

+0

Peut-être juste un pépin de phrasé - mais la performance nulle est la production serait mauvaise. Peut-être que vous voulez dire des frais généraux proches de zéro. –

+4

Assertions? Hm, 'console.assert()'? –

+0

@ Marc B: vous avez raison :) le réparer. – BreakPhreak

Répondre

6

Deux solutions possibles:

Demandez à votre script version build supprimer les lignes Assert.

ou

Demandez à votre script de compilation remplacer la fonction Assert il est donc juste une fonction vide. L'inconvénient de ceci est que si vous affirmez que l'appel a une logique dedans [alias assert (x> 100, "foo")] que cette logique [x> 100] va encore être exécutée.

+0

convenu! donc, aucun moyen de rendre le calcul des arguments nul, non? – BreakPhreak

+0

Le seul moyen est de le supprimer, ou de changer le langage d'assertion pour qu'il ressemble plus à jUnit/JSUnit/QUnit où vous avez différents contrôles assertTrue, assertFalse, assertEquals, assertNotSame. – epascarello

+0

Sur le point d'approuver la réponse. Juste SI possible - pourriez-vous clarifier sur ce dernier? Comme, si j'ai 'assertTrue (a! = B)' - quelle astuce puis-je appliquer, de sorte que 'a! = B' ne sera pas calculé en mode production (moins de surcharge)? – BreakPhreak

4

Voici ce que j'utiliser:

Quand je travaille sur le code que j'ai initDevMode(); en haut du fichier avec lequel je travaille, et quand je suis prêt à sortir en production, je supprime juste cette ligne et toutes les assertions vont juste à une fonction vide.

/** 
* Log a message to console: 
* either use jquery's console.error 
* or a thrown exception. 
* 
* call initDevMode(); before use to activate 
* use with: 
*  assert(<condition>, "message"); 
*  eg: assert(1 != 1, "uh oh!"); 
* 
* Log errors with: 
*  errorLog(message); 
*  eg: errorLog(xhr.status); 
*/ 
assert = function(test, msg) { } 
errorLog =function(msg) { } 

initDevMode = function() { 
    assert = function(test, msg) { 
     msg = msg || "(no error message)"; 
     if(!test) { 
      try { 
        throw Error(); 
       } catch(e) { 
        var foo = e; 
        var lines = e.stack.split('\n'); 
        for(i in lines) { 
         if(i > 2) { 
         errorLog(msg + lines[i]); 
        } 
       } 
      } 
     } 
     throw("Assertion failed with: " + msg); 
    }; 
    errorLog = function(msg) { 
     if(typeof console.error == 'function') { 
      console.error(msg); 
     } else { 
      function errorLog(msg) { 
       console.log("foo"); 
       setTimeout(function() { 
        throw new Error(msg); 
       }, 0); 
      } 
     } 
    }; 
} 
+1

Est-ce que 'throw ("Assertion failed") ne devrait pas' résident à l'intérieur 'du bloc if (! Test)'? –

0

Regardez Jascree; Fondamentalement, c'est un outil qui peut supprimer les assertions avec une logique presque arbitraire de votre code. C'est pratique à utiliser en tant que processeur par lots pour générer votre code de production ou pour un répertoire de scripts soutenu par fastcgi que vous pouvez utiliser lorsque vous avez besoin de tester les performances/profiler votre code.

2

J'utilise ce qui suit pour remplacer console.assert lorsqu'elle n'est pas disponible pour une raison quelconque.

Ce n'est certainement pas un standard de facto, et il est loin d'être idéal, mais il satisfait votre exigence que l'assertion ne soit pas évaluée en mode production. En outre, il vous montre l'expression qui a déclenché l'assertion échouée, ce qui facilite le débogage.

La syntaxe d'appel visqueuse (avec une expression de fonction) est là pour créer une fermeture, de sorte que la fonction assert a accès aux mêmes variables auxquelles son appelant a accès.

Je suppose que cela a un temps de compilation et d'exécution élevé, mais je n'ai pas essayé de le vérifier.

function assert(func) { 
    var name; 
    if (typeof(ENABLE_ASSERTIONS) !== "undefined" && !ENABLE_ASSERTIONS) { 
     return; 
    } 
    name = arguments.callee.caller; 
    name = name ? name.name : "(toplevel)"; 
    if (!func()) { 
     throw name + ": assertion failed: " + ('' + func).replace(/function[^(]*\([^)]*\)[^{]*{[^r]*return/, '').replace(/;[ \t\n]*}[ \t\n]*$/, ''); 
    } 
} 

Son utilisation ressemble:

function testAssertSuccess() { 
    var i = 1; 
    assert(function() { return i === 1; }); 
} 
function testAssertFailure() { 
    var j = 1; 
    assert(function() { return j === 2; }); 
} 
ENABLE_ASSERTIONS = true; 
testAssertSuccess(); 
testAssertFailure(); 

HTH!