Статьи

Тестирование приложений socket.io

Нян кошка тестирует

Socket.io, пожалуй, одна из самых крутых вещей, появившихся в мире JavaScript за последние годы. В заключение! Это то, что позволяет веб-разработчикам создавать приложения в реальном времени, не задумываясь о веб-сокетах, длительных опросах и других хакерских атаках, которые необходимо использовать.

Идея довольно проста: сервер может генерировать событие, а клиент его принимает . Обратное также происходит. Обратные вызовы через барьер сервер-клиент также работают. Socket.io заботится о том, чтобы решить, какой из хаков в реальном времени следует использовать, чтобы волшебство произошло.

Дело в том, что взаимодействие клиента и сервера делает приложения socket.io немного сложными для тестирования.

Хороший способ, который я нашел, — это сочетание Mocha , Chai и socket.io-client .

Сначала что-то для тестирования

Давайте возьмем для примера очень простой эхо-сервер. Я использовал  Express,  чтобы было легче играть в консоли Chrome. Вот соответствующая часть  app.js .

var server = exports.server = http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});
 
var io = require('socket.io').listen(server);
io.set("log level", 0);
// the important parts of echo server
io.sockets.on("connection", function (socket) {
    socket.on("echo", function (msg, callback) {
        callback = callback || function () {};
 
        socket.emit("echo", msg);
 
        callback(null, "Done.");
    });
});

После того, как я не забыл загрузить /socket.io/socket.io.js на страницу индекса, я теперь могу запустить сервер, указать свой браузер на  http: // localhost: 3000 и поиграть в консоли следующим образом:

> var socket = io.connect("http://localhost:3000")
undefined
> socket.on("echo", function (msg) { console.log(msg); })
SocketNamespace
> socket.emit("echo", "Hello World")
SocketNamespace
Hello World

Автоматизация теста

Ввод команд в консоли, даже нажатие на веб-страницу — довольно трудный и скучный процесс. Самый простой способ, который я нашел, это автоматизировать с помощью Mocha и socket.io-client.

Первое, что нам нужно, — это требовать всего и убедиться, что сервер socket.io работает.

var chai = require('chai'),
    mocha = require('mocha'),
    should = chai.should();
 
var io = require('socket.io-client');
 
describe("echo", function () {
 
    var server,
        options ={
            transports: ['websocket'],
            'force new connection': true
        };
 
    beforeEach(function (done) {
        // start the server
        server = require('../app').server;
 
        done();
    });

Смотри, просто :)

Теперь перейдем к интересной части, собственно тесту, удостоверяющему, что наш сервер действительно повторяет то, что мы просим.

    it("echos message", function (done) {
        var client = io.connect("http://localhost:3000", options);
 
        client.once("connect", function () {
            client.once("echo", function (message) {
                message.should.equal("Hello World");
 
                client.disconnect();
                done();
            });
 
            client.emit("echo", "Hello World");
        });
    });

Идея этого теста проста:

  1. Подключите клиент к серверу
  2. Когда соединение установлено, прослушайте  эхо- событие с сервера
  3. Выдать эхо-  событие на сервер
  4. Сервер отвечает и запускает нашего слушателя
  5. Слушатель проверяет правильность ответа
  6. Отключает клиента

Отключение клиентов после тестов  очень важно . Как я обнаружил, отсутствие разъединения может привести к тому, что сокет накапливает прослушиватели событий , которые в свою очередь могут запускать совершенно другие тесты, чем вы ожидаете. Это также приводит к тестам, которые проходят 70% времени, но не дают результатов случайным образом.

В итоге наши усилия вознаграждаются счастливой нянькой кошкой.

Нян кошка тестирует

PS: вы можете увидеть весь код на github .