Simian, aka Similarity Analyser est un outil des plus merveilleux. Il analysera vos lignes de code et détectera des potentielles répétitions.

A cela, nous couplons un gem de Jean-Michel Garnier (qui était présent au RubyCamp Lyonnais), Don’t Repeat Yourself.
Et à partir de maintenant, nous pouvons tester que nos applications Ruby et Rails sont DRY !!
J’ai testé et ça fonctionne plutôt du tonnerre.

Installation du plugin :
Si vous n’avez pas encore le catalogue de gems de GitHub, ajoutez-le :
gem sources -a http://gems.github.com
Puis installez le gem.
gem install dmathieu-dont_repeat_yourself
Vous constaterez que je vous fait installer non pas la version de Jean-Michel, mais la mienne. Les explications viennent plus bas.

Une fois que cela est fait, vous pouvez utiliser le plugin de trois manières possibles.

Dans vos tests

Avec Test::Unit

Créez le test suivant :
test "we don't repeat ourself" do
  assert_dry(rails_application.with_netbeans_reporting)
end

Avec RSpec

Créez le test suivant :
describe "Dupplicate lines Report: Don't Repeat Yourself" do
  it { ruby_project(File.dirname(__FILE__) + '/../').
    with_threshold_of_duplicate_lines(4).
    with_netbeans_reporting.
    should follow_the_dry_principle }
end

En ligne de commande

Tapez la commande suivante
dry-report

Ces rapports DRY sont même encapsulables dans Netbeans ou Textmate. Mais je n’ai pas encore penché mon nez là-dedans. Donc je vous laisse regarder ;)

Vous constaterez par ailleurs que je vous invite à installer le fork que j’ai fait du gem et non pas la version originelle.
La raison à cela est que en Rails 2.3, Test::Unit deviens ActiveSupport::TestCase.
Cette modification n’a pas encore été appliquée au gem originel. Mais je suis persuadé que cela ne saurait tarder ;)

J’ai déjà parlé plusieurs fois ici de tests unitaires. En Ruby ou en PHP.
Cependant toute application qui se respecte aura également une couche navigateur, permettant d’ajouter de l’ajax par exemple.
Ces fonctionnalités, tout comme le code serveur, sont testables.

Voyons un petit peu comment cela fonctionne avec QUnit, le framework de tests unitaires intégré avec JQuery.

Pour cela, je vais reprendre mon exemple d’il y a quelques mois ou je proposais de signaler si un pseudonyme est déjà utilisé lors d’une inscription, et de tester cela.
Cependant aujourd’hui, j’ai fait la chose en PHP, afin d’épargner la création d’un projet RoR. On a au final, dans cet exemple, besoin que de deux fichiers :

check_user.php, qui vérifie si notre pseudonyme est disponible ou non. Et retourne ‘OK’ si il l’est et ‘NOT’ sinon.
On ne s’embête pas ici. Voici ce que j’ai dans mon document :

<?php if ($_GET['u'] == 'oh') echo 'OK';
else echo 'NOT'; ?>

Puis dans notre index.php, nous allons placer le champ de texte du nom d’utilisateur.

<html>
    <head>
        <title></title>
        <script src="http://www.google.com/jsapi"></script>
        <script type="text/javascript>
            google.load("jquery", "1.3.2");
        </script>
        <script type="text/javascript" src="code.js"></script>
    </head>
    <body>
        <input type="text" id="username" name="username" />
        <div id="availability"></div>
    </body>
</html>

Et nous appellons notre document javascript qui fera un appel ajax à check_user.php.

$(document).ready(function() {
    $('#username').blur(function () {
        username = $('#username').val();
        if (username == '') {
            $('#availability').html('');
            return false;
        }

        $.ajax({
            url: 'check_user.php?u='+username,
            success: function(data) {
                    if (data == 'OK') {
                        $('#availability').html('Disponible');
                        $('#availability').css('color', 'green');
                    } else {
                        $('#availability').html('Non disponible');
                        $('#availability').css('color', 'red');
                    }
            },
            error: function(data) {
                $('#availability').html('');
            }
        });
    })
});

Voila ! Maintenant, nous avons notre test de validité de l’utilisateur de fonctionnel. Pour l’instant du moins car pour être sur qu’il le reste, nous allons ajouter des tests.
Commençons par implémenter QUnit dans notre index.php.

<html>
    <head>
        <title></title>

        <script src="http://www.google.com/jsapi"></script>
        <script type="text/javascript">
            google.load("jquery", "1.3.2");
        </script>
        <script type="text/javascript" src="code.js"></script>
    </head>
    <body>

        <input type="text" id="username" name="username" />
        <div id="availability"></div>

        <link rel="stylesheet" href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" type="text/css" media="screen" /
	<script type="text/javascript" src="http://github.com/jquery/qunit/raw/master/qunit/qunit.js"></script>
        <script type="text/javascript" src="tests.js"></script>
        <h2 id="qunit-banner">Qunit Testing</h2>
	<h2 id="qunit-userAgent"></h2>
	<ol id="qunit-tests"></ol>
    </body>
</html>

Vous pouvez constater que nous ajoutons divers tags html en fin de page. Ceux-ci seront automatiquement remplacés par l’interface de visualisation des tests.

Et enfin dans le fichier tests.js inclus précédemment, nous plaçons tous nos tests.

$.ajaxSetup({
  async: false
});

module("username")

test("availability div shouldn't have any value by default", function() {
    equals($('#availability').html(), '', "availability div doesn't have any value by default");
});

test("should allow inexistant username", function() {
    $('#username').val('oh');
    $('#username').blur();

    equals($('#availability').html(), 'Disponible', "the username is available");
    equals($('#availability').css('color'), 'green', "the username is available");
});

test("should not allow existant username", function() {
    $('#username').val('doh');
    $('#username').blur();

    equals($('#availability').html(), 'Non disponible', "the username is not available");
    equals($('#availability').css('color'), 'red', "the username is not available");
});

test("should hide the message if username is empty", function() {
    $('#username').val('');
    $('#username').blur();

    equals($('#availability').html(), '', "the username is empty");
})

La méthode « module » permet de signaler que nous sommes dans la partie de vérification du pseudonyme de la page.
Chaque méthode test définit un test.

Quant au ajaxSetup, il nous permet de forcer les requêtes ajax à ne pas être asynchrone. Si elles l’étaient, nos tests seraient exécutés avant le retour de la requête ajax et échoueraient donc.

Si vous rechargez votre page, vous pouvez maintenant voir que nous testons convenablement (et avec succès) la vérification de la disponibilité de notre pseudonyme.

Pour finir, vous me direz rapidement que c’est bien gentil de tester ça. Mais que vous n’allez pas charger chacune des pages de votre site à chaque fois que vous changez une ligne de code.
La solution à cela, qui est cependant trop complexe pour tenir dans cet article, est d’utiliser Selenium, un outil permettant de tester le frontend d’une application web sur de multiples navigateurs.

Pour finir, vous pouvez voir toutes les portions de code données dans cet article avec mise en couleur du code.

 
Fork me on GitHub