Как выполнить много тестов процесса в Мокко? - PullRequest
0 голосов
/ 28 мая 2018

У меня есть репозиторий с ~ 70 тестами исполняемых файлов.При работе под mocha или jest обычно он получает либо ошибки в первых обещаниях пары, либо из-за тайм-аута, либо потому, что stdout никогда не возвращался в родительский процесс.

Моя минимальная репликация этой проблемы включает 100 потоков, каждый из которых вызывает командную строку, которая спит в течение 10 секунд:

let child_process = require('child_process');
let AllTests = [];

/* start processes */
for (let i = 0; i < 100; ++i) {
  AllTests.push({
    i: i,
    start: new Date(),
    exec: new Promise((resolve, reject) => {
      let program = child_process.spawn(
        'node', ['-e', 'setTimeout(() => { process.exit(0); }, 9999)'])
        // 'node', ['-e', 'for (let i = 0; i < 2**28; ++i) ;'])
      program.on('exit', exitCode => { resolve({exitCode:exitCode}) })
      program.on('error', err => { reject(err) })
    })
  })
}

/* test results */
describe('churn', () => {
  AllTests.forEach(test => {
    it('should execute test ' + test.i + '.',
       done => {
         test.exec.then(exec => {
           test.end = new Date()
           done()
         })
       })
  })
})

На моем ноутбуке с недостаточным питанием я обычно получаю:

  93 passing (19s)
  7 failing

  1) churn
       should execute test 0.:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/eric/errz/flood.js)
  ...

Добавление некоторого учета впоследствии:

after(() => {
  console.log()
  AllTests.forEach(test => {
    console.log(test.i, (test.end - test.start)/1000.0)
  })
})

показывает, что каждый процесс занимает ~ 19 с.

Учитывая, что это происходит в Mocha и Jest, я думаю, что проблема связана с 100 одновременнымипроцессы.Предложения?

1 Ответ

0 голосов
/ 01 июня 2018

Я мог бы почти решить проблемы тайм-аутов и потока stdio отдельно.Проблемы с потоком в основном прояснились, когда я отправил обработчик выхода для завершения процесса в следующий цикл событий:

program.on("exit", function(exitCode) {
  setTimeout(
    () => resolve({stdout:stdout, stderr:stderr, exitCode:exitCode}), 0
  )
});
program.on("error", function(err) { reject(err); });

Тайм-ауты были из-за того, что я заполнял таблицу процессов.Вместо того, чтобы слишком тесно связываться с планировщиком ядра, я использовал timeout-обещание-очередь , который ограничивал общее количество одновременных процессов и предоставлял тайм-ауты на основе времени начала каждого процесса в очереди.

Использование timeout-обещание-очередь также устранило проблемы с потоками воспроизведения, которые появлялись только тогда, когда таблица процессов становилась слишком большой.После тысяч тестов я остановился на очереди процессов 25 и на тайм-ауте длины 0 на обработчике выхода.

Итоговые различия довольно минимальны и говорят сами за себя, и я небольше нужно нажать [estRestart job] на тестах Трэвиса .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...