2015-05-16 2 views
0

Я написал несколько модульных тестов для API, управляемых node.js, который я построил с использованием Jasmine.Тесты Jasmine async внутри цикла работают не так, как ожидалось

Тесты работают нормально, но теперь я хотел бы запустить набор асинхронных тестов с различными входами, но я не могу заставить его работать.

Мои тесты запускают некоторые запросы против API с параметром «смещение» и «ограничение» в URL-адресе, а API вставляет ссылки для разбивки на страницы в ответе (во-первых, предыдущий, следующий и последний).

Вот мой Жасмин тест:

describe('API with "limit" and "offset" parameters', function() { 

    var offset = 0; 
    var limit = 4; 
    var url = baseUrl + '?limit=' + limit + '&offset=' + offset; 

    beforeEach(function(done) { 
     request.get(url, function(err, res, resBody) { 
      response = res; 
      body = JSON.parse(resBody); 
      count = body.count; 
      done(); 
     }); 
    }); 

    it('should respond with status code 200', function(done) { 
     expect(response.statusCode).toEqual(200); 
     done(); 
    }); 

    it('should have a response with [limit] results if count - offset >= limit, otherwise count - offset', function(done) { 
     if(count - offset >= limit) expect(body.rows.length).toEqual(limit); 
     else expect(body.rows.length).toEqual(count - offset); 
     done(); 
    }); 

    it('should have navigation links', function(done) { 
     expect(body.first).toBeDefined(); 
     expect(body.prev).toBeDefined(); 
     expect(body.next).toBeDefined(); 
     expect(body.last).toBeDefined(); 
     done(); 
    }); 

    it('should have "first" navigation link equal to url offset=0 and limit=limit', function(done) { 
     expect(body.first).toEqual(baseUrl + '?limit=' + limit + '&offset=0'); 
     done(); 
    }); 

    it('should have "prev" navigation link equal to null if offset=0, otherwise offset = offset - limit', function(done) { 
     if(offset ===0) expect(body.prev).toBeNull(); 
     else expect(body.prev).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset - limit)); 
     done(); 
    }); 

    it('should have "next" navigation link equal to offset + limit, or null if offset+limit > count', function(done) { 
     if(offset + limit <= count) expect(body.next).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset + limit)); 
     else expect(body.next).toBeNull(); 
     done(); 
    }); 

    it('should have "last" navigation link equal to floor(count/limit)*limit', function(done) { 
     expect(body.last).toEqual(baseUrl + '?limit=' + limit + '&offset=' + Math.floor(count/limit) * limit); 
     done(); 
    }); 
}); 

Этот тест работает нормально, но сейчас я хотел бы повторно запустить этот тест, в каждом цикле увеличивающегося «смещение» на «предел», пока последняя страница не будет достигнут (т.е. offset + limit> = count), но я не могу заставить это работать.

То, что я пытался до сих пор

Моя первая идея состояла в том, чтобы поставить тесты внутри цикла, помещенные в IIFE, но это не работает, потому что «счет» в течение петли не определено (Я предполагаю, что это доступно только внутри «это»):

for(var i=offset; i<count; i+=limit) { // "count" is undefined here 

     (function(offset, count, limit) { 

      it('should have "first" navigation link equal to url offset=0 and limit=limit', function(done) { 
       expect(body.first).toEqual(baseUrl + '?limit=' + limit + '&offset=0'); 
       done(); 
      }); 

      it('should have "prev" navigation link equal to null if offset=0, otherwise offset = offset - limit', function(done) { 
       if(offset ===0) expect(body.prev).toBeNull(); 
       else expect(body.prev).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset - limit)); 
       done(); 
      }); 

      it('should have "next" navigation link equal to offset + limit, or null if offset+limit > count', function(done) { 
       if(offset + limit <= count) expect(body.next).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset + limit)); 
       else expect(body.next).toBeNull(); 
       done(); 
      }); 

      it('should have "last" navigation link equal to floor(count/limit)*limit', function(done) { 
       expect(body.last).toEqual(baseUrl + '?limit=' + limit + '&offset=' + Math.floor(count/limit) * limit); 
       done(); 
      }); 
     })(offset, count, limit); 
    } 

Моя вторая идея состояла в том, чтобы сделать увеличивающиеся внутри «Afterall», снова заворачивая испытаний в IIFE. Кажется, что Afterall мчит runTests() еще раз (я вижу console.log появляющийся), но сами тесты не выполняются снова:

(function runTests(offset, count, limit) { 
     console.log('running tests'); 
     beforeEach(function(done) { 
      request.get(url, function(err, res, resBody) { 
       response = res; 
       body = JSON.parse(resBody); 
       count = body.count; 
       done(); 
      }); 
     }); 

     it('should have "first" navigation link equal to url offset=0 and limit=limit', function(done) { 
      expect(body.first).toEqual(baseUrl + '?limit=' + limit + '&offset=0'); 
      done(); 
     }); 

     it('should have "prev" navigation link equal to null if offset=0, otherwise offset = offset - limit', function(done) { 
      if(offset ===0) expect(body.prev).toBeNull(); 
      else expect(body.prev).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset - limit)); 
      done(); 
     }); 

     it('should have "next" navigation link equal to offset + limit, or null if offset+limit > count', function(done) { 
      console.log('next', offset, limit, count); 
      if(offset + limit <= count) expect(body.next).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset + limit)); 
      else expect(body.next).toBeNull(); 
      done(); 
     }); 

     it('should have "last" navigation link equal to floor(count/limit)*limit', function(done) { 
      expect(body.last).toEqual(baseUrl + '?limit=' + limit + '&offset=' + Math.floor(count/limit) * limit); 
      done(); 
     }); 

     afterAll(function() { 
      offset += limit; 

      if(offset < count) runTests(offset, count, limit); 
     }); 
    })(offset, count, limit); 

Что я здесь делаю неправильно? Есть ли другой способ заставить это работать?

UPDATE: вот мой полный рабочий код, основанный на ответ Златко в:

describe('API with "limit" and "offset" parameters', function() { 

    var offset = 0; 
    var limit = 4; 
    var url = baseUrl + '?limit=' + limit + '&offset=' + offset; 

    function testNavLinks(limit, offset, url) { 

     describe('Check navigation links with offset = ' + offset, function() { 

      var response; 
      var count; 
      var body; 

      beforeEach(function(done) { 
       request.get(url, function(err, res, resBody) { 
        response = res; 
        body = JSON.parse(resBody); 
        count = body.count; 
        done(); 
       }); 
      }); 

      it('should respond with status code 200', function(done) { 
       expect(response.statusCode).toEqual(200); 
       done(); 
      }); 

      it('should have a response with [limit] results if count - offset >= limit, otherwise count - offset', function(done) { 
       if(count - offset >= limit) expect(body.rows.length).toEqual(limit); 
       else expect(body.rows.length).toEqual(count - offset); 
       done(); 
      }); 

      it('should have navigation links', function(done) { 
       expect(body.first).toBeDefined(); 
       expect(body.prev).toBeDefined(); 
       expect(body.next).toBeDefined(); 
       expect(body.last).toBeDefined(); 
       done(); 
      }); 

      it('should have "first" navigation link equal to url offset=0 and limit=limit', function(done) { 
       expect(body.first).toEqual(baseUrl + '?limit=' + limit + '&offset=0'); 
       done(); 
      }); 

      it('should have "prev" navigation link equal to null if offset=0, otherwise offset = offset - limit', function(done) { 
       if(offset === 0) expect(body.prev).toBeNull(); 
       else expect(body.prev).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset - limit)); 
       done(); 
      }); 

      it('should have "next" navigation link equal to offset + limit, or null if offset+limit > count', function(done) { 
       if(offset + limit <= count) expect(body.next).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset + limit)); 
       else expect(body.next).toBeNull(); 
       done(); 
      }); 

      it('should have "last" navigation link equal to floor(count/limit)*limit', function(done) { 
       expect(body.last).toEqual(baseUrl + '?limit=' + limit + '&offset=' + Math.floor(count/limit) * limit); 
       done(); 
      }); 
     }); 
    } 
    // 13 is the actual number of results 
    // I did not manage to get the actual number from the response, see my comment below 
    for(var i=0; i<13; i+=limit) { 
     url = baseUrl + '?limit=' + limit + '&offset=' + i; 
     testNavLinks(limit, i, url); 
    } 
}); 

ответ

0

Так вы пытаетесь повторить тест, несколько раз, но нет никакой необходимости иметь дело с IIFE вообще. Просто сделайте свой тест функцией, затем вызовите его из цикла:

describe('Loop an async set of tests.', function() { 

    var baseUrl = process.env.API_URL; // or whatever 
    function loopMyApi(offset, limit) { 

    // add a new suite 
    describe('Calling at offset: ' + offset , function() { 

     var response; 
     var myUrl = baseUrl + '?limit=' + limit + '&offset=' + offset; 
     beforeEach(function(done) { 

     request(myUrl, function(err, res) { 

      if (err) {throw err;} 
      response = res; 
      done(); 
     }); 
     }); 

     it('should have length', function() { 

     // btw since response is already here, this test is now sync 
     // no need for `done`. 
     response.body.length.should.equal(limit); 
     }); 
     it('should be ok', function() { 
     response.statusCode.should.be.lessThan(399); 
     }); 
    }); 
    } 
    var limit = 10; 
    // you can start like this, or just make a regular for 
    // loop as you have in your examples. 
    [0, 10, 20, 30].forEach(function(offset) { 

    // if you want to modify limit for some reason, do it here. 
    loopMyApi(offset, limit); 
    }); 
}); 

Отрегулируйте по мере необходимости, чтобы соответствовать вашему сценарию.

+0

Спасибо, я получил это сейчас. Единственным недостатком является то, что мне приходится жестко кодировать количество результатов (переменную count) в for-loop. Моя идея состояла в том, чтобы получить число результатов в родительском «описать», но это не работает, поскольку for-loop, по-видимому, запускается до запуска каких-либо спецификаций (я вижу console.log внутри цикла как самый первый вывод) –

+0

Не уверен, что я понял, о чем вы просите, но если да, то вы также можете сделать 'beforeEach()' во внешнем 'описании' и запустить цикл for оттуда? Хм. Я просто задаюсь вопросом, будет ли он обработан, потому что «каждый» не запускается раньше каждого раньше :) – Zlatko

Смежные вопросы