簡體   English   中英

運行序列同步任務永遠不會完成

[英]run-sequence synchronous task never completes

我幾乎肯定會以錯誤的方式進行此操作,因此首先提出我的高級要求。

我正在使用angular2種子,並希望通過使用Xvfb在無頭模式下運行量角器測試。 我不希望Xvfb服務器一直運行(這是一個構建服務器),所以我想啟動Xvfb服務,讓Protractor完成它,然后“優雅地”關閉Xvfb。 孤立地,這些任務運行良好,但是在將它們添加到gulp構建設置中時遇到了麻煩。

這是gulpfile中的任務:

gulp.task('e2e.headless', (done: any) =>
  runSequence('start.xvfb',
              'protractor',
              'stop.xvfb',
              done));

任務本身通過單獨的打字稿任務文件加載,即:

import {runProtractor} from '../../utils';

export = runProtractor

這是我(最新的)實用程序文件本身。

量角器

import * as util from 'gulp-util';
import {normalize, join} from 'path';
import {ChildProcess} from 'child_process';

function reportError(message: string) {
  console.error(require('chalk').white.bgRed.bold(message));
  process.exit(1);
}

function promiseFromChildProcess(child: ChildProcess) {
  return new Promise(function (resolve: () => void, reject: () => void) {
    child.on('close', (code: any) => {
      util.log('Exited with code: ', code);
      resolve();
    });
    child.stdout.on('data', (data: any) => {
      util.log(`stdout: ${data}`);
    });

    child.stderr.on('data', (data: any) => {
      util.log(`stderr: ${data}`);
      reject();
    });
  });
}

export function runProtractor(): (done: () => void) => void {
  return done => {
    const root = normalize(join(__dirname, '..', '..', '..'));
    const exec = require('child_process').exec;

    // Our Xvfb instance is running on :99
    // TODO: Pass this in instead of hard-coding
    process.env.DISPLAY=':99';
    util.log('cwd:', root);

    let child = exec('protractor', { cwd: root, env: process.env},
      function (error: Error, stdout: NodeBuffer, stderr: NodeBuffer) {
        if (error !== null) {
          reportError('Protractor error: ' + error + stderr);
        }
      });
    promiseFromChildProcess(child).then(() => done());
  };
}

xvfb_tools.ts

import * as util from 'gulp-util';

const exec = require('child_process').exec;

function reportError(message: string) {
  console.error(require('chalk').white.bgRed.bold(message));
  process.exit(1);
}

export function stopXvfb() {
    return exec('pkill -c -n Xvfb',
        function (error: NodeJS.ErrnoException, stdout: NodeBuffer, stderr: NodeBuffer) {
            if (error !== null) {
                reportError('Failed to kill Xvfb.  Not really sure why...');
            } else if (stdout.toString() === '0') {
                reportError('No known Xvfb instance.  Is it running?');
            } else {
                util.log('Xvfb terminated');
            }
        });
}

export function startXvfb() {
    return exec('Xvfb :99 -ac -screen 0 1600x1200x24',
        function (error: NodeJS.ErrnoException, stdout: NodeBuffer, stderr: NodeBuffer) {
            if (error !== null && error.code !== null) {
                reportError('Xvfb failed to start.  Err: ' + error.code + ', ' + error + ', ' + stderr);
            }
        });
}

我覺得好像我可能正在exec child_process來創建一個承諾,但是在代碼的早期交互中並沒有做到這一點,所以...請注意,調試日志記錄應該在runProtractor()輸出顯示根目錄永遠不會被調用,所以我很確定這里存在一個異步問題。 這是任務的輸出:

[00:47:49] Starting 'e2e.headless'...
[00:47:49] Starting 'start.xvfb'...
[00:47:49] Finished 'start.xvfb' after 12 ms
[00:47:49] Starting 'protractor'...
[00:47:49] Finished 'protractor' after 5.74 ms
[00:47:49] Starting 'stop.xvfb'...
[00:47:49] Finished 'stop.xvfb' after 11 ms
[00:47:49] Finished 'e2e.headless' after 38 ms
[00:47:49] Xvfb terminated

有人可以讓我伸直/將我推向正確的方向嗎?

您需要在gulp任務中添加一個回調函數,並在所有runSequence任務完成后調用cb(回調)函數。

gulp.task('e2e.headless', (cb) =>
runSequence('start.xvfb',
    'protractor',
    'stop.xvfb',
     (err) => {
        if (err) {
            console.log(err.message);
        } else {
            console.log("Build finished successfully");
        }
        cb(err);
    });
});

感謝angular2種子團隊的Ludovic!

錯誤在於沒有從包裝類中調用runProtractor函數,即export = runProtractor() 一旦注意到這一點,我就可以去除不必要的包裝函數以及promiseFromChildProcess,這是分心的。

最后的任務只是一個匿名函數,該函數接受退出時調用的gulp回調:

function reportError(message: string) {
  console.error(require('chalk').white.bgRed.bold(message));
  process.exit(1);
}

export = (done: any) => {
    const root = normalize(join(__dirname, '..', '..', '..'));
    const exec = require('child_process').exec;

    process.env.DISPLAY=':99';
    util.log('cwd:', root);

    exec('protractor', { cwd: root, env: process.env},
      function (error: Error, stdout: NodeBuffer, stderr: NodeBuffer) {
        if (error !== null) {
          reportError('Protractor error: ' + error + stderr);
        } else {
          done();
        }
      });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM