Chai Exec

用於測試您的 CLI 的 Chai 斷言

Cross-Platform Compatibility Build Status

Coverage Status Dependencies

npm License Buy us a tree

功能

  • 易於使用
    將您的 CLI 和參數作為單一字串、字串陣列或單獨的參數傳遞。

  • 不要重複自己
    設定您的通用預設值一次。 每個測試只需要指定對其獨特的參數。

  • 流暢的斷言
    使用直觀的流暢語法測試您的 CLI,例如 myCLI.should.exit.with.code(0)myCLI.stdout.should.contain("某個字串")

  • 非同步支援
    只需使用 await chaiExecAsync() 代替 chaiExec()。 其他一切都相同。

  • Windows 支援
    感謝cross-spawn,提供出色的 Windows 支援。

  • ez-spawn - 簡單、一致的程序產生

範例

const chaiExec = require("@jsdevtools/chai-exec");
const chai = require("chai");

chai.use(chaiExec);

describe("My CLI", () => {
  it("should exit with a zero exit code", () => {
    // Run your CLI
    let myCLI = chaiExec('my-cli --arg1 --arg2 "some other arg"');

    // Should syntax
    myCLI.should.exit.with.code(0);
    myCLI.stdout.should.contain("Success!");
    myCLI.stderr.should.be.empty;

    // Expect sytnax
    expect(myCLI).to.exit.with.code(0);
    expect(myCLI).stdout.to.contain("Success!");
    expect(myCLI).stderr.to.be.empty;

    // Assert syntax
    assert.exitCode(myCLI, 0);
    assert.stdout(myCLI, "Success!");
    assert.stderr(myCLI, "");
  });
});

安裝

使用 npm 安裝

npm install @jsdevtools/chai-exec

然後在您的測試檔案中引入它並向 Chai 註冊

const chaiExec = require("@jsdevtools/chai-exec");
const chai = require("chai");

chai.use(chaiExec);

用法

chaiExec(cli, [args], [options])

您可以將您的 CLI 及其參數作為單一字串、字串陣列或單獨的參數傳遞。 以下範例都執行相同的操作

chaiExec(`git commit -am "Fixed a bug"`);           // Pass the CLI and args as a single string
chaiExec("git", "commit", "-am", "Fixed a bug");    // Pass the CLI and args as separate params
chaiExec(["git", "commit", "-am", "Fixed a bug"]);  // Pass the CLI and args as an array
chaiExec("git", ["commit", "-am", "Fixed a bug"]);  // Pass the CLI as a string and args as an array

有關options 參數的詳細資訊,請參閱 ez-spawn 選項

chaiExecAsync(cli, [args], [options])

chaiExecAsync() 函數的工作方式與 chaiExec() 完全相同,只是它以非同步方式執行您的 CLI 並傳回一個 Promise,該 Promise 在 CLI 退出時解析。 您需要像這樣明確要求 chaiExecAsync 導出

const { chaiExecAsync } = require("@jsdevtools/chai-exec");

然後您可以像使用 chaiExec 一樣使用 chaiExecAsync,但請記得使用 asyncawait 關鍵字,因為它是非同步的。

const { chaiExecAsync } = require("@jsdevtools/chai-exec");
const chai = require("chai");

chai.use(chaiExecAsync);

describe("My CLI", () => {
  it("should exit with a zero exit code", async () => {
    // Run your CLI
    let myCLI = await chaiExecAsync('my-cli --arg1 --arg2 "some other arg"');

    // Should syntax
    myCLI.should.exit.with.code(0);
    myCLI.stdout.should.contain("Success!");
    myCLI.stderr.should.be.empty;

    // Expect sytnax
    expect(myCLI).to.exit.with.code(0);
    expect(myCLI).stdout.to.contain("Success!");
    expect(myCLI).stderr.to.be.empty;

    // Assert syntax
    assert.exitCode(myCLI, 0);
    assert.stdout(myCLI, "Success!");
    assert.stderr(myCLI, "");
  });
});

chaiExec.defaults

在編寫 CLI 測試時,您通常會希望對每個測試使用相同的命令、args 和/或選項。 您可以設定 chaiExec.defaults 一次,而不是每次呼叫 chaiExec 時都重複相同的參數。 您的預設值將用於每個後續的 chaiExec() 呼叫。 除了預設值之外,您還可以為每次呼叫指定額外的 CLI 參數和/或選項。

  • defaults.command (字串)
    您的 CLI 的名稱或路徑。 設定一次,然後您只需要將參數傳遞給 chaiExec()

  • defaults.args (字串或字串陣列)
    每次都傳遞給您的 CLI 的參數。 如果您在呼叫 chaiExec() 時傳遞額外的參數,它們將附加到預設參數。

  • defaults.options (選項物件)
    每次都使用的預設選項。 如果您在呼叫 chaiExec() 時傳遞額外的選項,它們將與預設參數合併。

const chaiExec = require("@jsdevtools/chai-exec");
const chai = require("chai");

chai.use(chaiExec);

// Set some defaults
chaiExec.defaults = {
  command: "my-cli",
  args: "--arg1 --arg2",
  options: {
    cwd: "/usr/bin"
  }
};

describe("My CLI", () => {
  it("should use defaults", () => {
    // Run your CLI using defaults + one-time args
    let myCLI("--arg3 --arg4");

    myCLI.command.should.equal("my-cli");
    myCLI.args.should.deep.equal([ "--arg1", "--arg2", "--arg3", "--arg4" ]);
  });
});

斷言

.exitCode(number, [message])

別名: .exit.code.status

斷言您的 CLI 的退出代碼。 您可以測試特定代碼、代碼列表或範圍。

// Should syntax
myCLI.exitCode.should.equal(0);
myCLI.should.have.exitCode(0);
myCLI.should.exit.with.code(0);
myCLI.should.exit.with.a.code.that.is.oneOf(0, [0, 1, 2, 3]);
myCLI.should.have.an.exit.code.of.at.least(0).and.at.most(5);

// Expect sytnax
expect(myCLI).exitCode.to.equal(0);
expect(myCLI).to.have.exitCode(0);
expect(myCLI).to.exit.with.code(0);
expect(myCLI).to.exit.with.a.code.that.is.oneOf([0, 1, 2, 3]);
expect(myCLI).to.have.an.exit.code.of.at.least(0).and.at.most(5);

// Assert syntax
assert.equal(myCLI.exitCode, 0);

assert.exitCode(myCLI, 0);
assert.exitCode(myCLI, [0, 1, 2, 3]);

assert.notExitCode(myCLI, 1);
assert.notExitCode(myCLI, [1, 2, 3]);

assert.exitCodeBetween(myCLI, 0, 5);
assert.exitCodeNotBetween(myCLI, 1, 5);

.stdout(string, [message])

斷言您的 CLI 的標準輸出 (非錯誤、非警告輸出)。 您可以測試特定字串、子字串或正規表示式。

// Should syntax
myCLI.stdout.should.equal("Success!");
myCLI.should.have.stdout.that.contains("Success!");
myCLI.should.have.stdout.that.does.not.contain("Failure!");
myCLI.should.have.stdout.that.matches(/^Success!$/);
myCLI.should.have.stdout.that.does.not.match(/^Failure!$/);

// Expect syntax
expect(myCLI).stdout.to.equal("Success!");
expect(myCLI).to.have.stdout.that.contains("Success!");
expect(myCLI).to.have.stdout.that.does.not.contain("Failure!");
expect(myCLI).to.have.stdout.that.matches(/^Success!$/);
expect(myCLI).to.have.stdout.that.does.not.match(/^Failure!$/);

// Assert syntax
assert.stdout(myCLI, "Success!");
assert.stdout(myCLI, /^Success!$/);

assert.include(myCLI.stdout, "Success!");
assert.notInclude(myCLI.stdout, "Failure!");

assert.match(myCLI.stdout, /^Success!$/);
assert.notMatch(myCLI.stdout, /^Failure!$/);

.stderr(string, [message])

斷言您的 CLI 的 stderr 輸出(錯誤和警告)。 您可以測試特定字串、子字串或正規表示式。

// Should syntax
myCLI.stderr.should.equal("Failure!");
myCLI.should.have.stderr.that.contains("Failure!");
myCLI.should.have.stderr.that.does.not.contain("Success!");
myCLI.should.have.stderr.that.matches(/^Failure!$/);
myCLI.should.have.stderr.that.does.not.match(/^Success!$/);

// Expect syntax
expect(myCLI).stderr.to.equal("Failure!");
expect(myCLI).to.have.stderr.that.contains("Failure!");
expect(myCLI).to.have.stderr.that.does.not.contain("Success!");
expect(myCLI).to.have.stderr.that.matches(/^Failure!$/);
expect(myCLI).to.have.stderr.that.does.not.match(/^Success!$/);

// Assert syntax
assert.stderr(myCLI, "Failure!");
assert.stderr(myCLI, /^Failure!$/);

assert.include(myCLI.stderr, "Failure!");
assert.notInclude(myCLI.stderr, "Success!");

assert.match(myCLI.stderr, /^Failure!$/);
assert.notMatch(myCLI.stderr, /^Success!$/);

.output(string, [message])

斷言您的 CLI 的所有輸出 (stdout + output)。 您可以測試特定字串、子字串或正規表示式。

// Should syntax
myCLI.output.should.equal("Success!");
myCLI.should.have.output.that.contains("Failure!");
myCLI.should.have.output.that.does.not.contain("Success!");
myCLI.should.have.output.that.matches(/^(Success|Failure)!$/);
myCLI.should.have.output.that.does.not.match(/^(Success|Failure)!$/);

// Expect syntax
expect(myCLI).output.to.equal("Success!");
expect(myCLI).to.have.output.that.contains("Failure!");
expect(myCLI).to.have.output.that.does.not.contain("Success!");
expect(myCLI).to.have.output.that.matches(/^(Success|Failure)!$/);
expect(myCLI).to.have.output.that.does.not.match(/^(Success|Failure)!$/);

// Assert syntax
assert.output(myCLI, "Failure!");
assert.output(myCLI, /^(Success|Failure)!$/);

assert.include(myCLI.output, "Failure!");
assert.notInclude(myCLI.output, "Success!");

assert.match(myCLI.output, /^Failure!$/);
assert.notMatch(myCLI.output, /^Success!$/);

貢獻

歡迎貢獻、增強和錯誤修復! 在 GitHub 上開啟一個問題提交一個提取請求

建置/測試

在本機電腦上建置/測試專案

  1. 複製這個 repo
    git clone hhttps://github.com/JS-DevTools/chai-exec.git

  2. 安裝依賴項
    npm install

  3. 執行測試
    npm test

授權

Chai Exec 根據 MIT 授權是 100% 免費且開源的。 隨心所欲地使用它。

此套件是Treeware。 如果您在生產環境中使用它,那麼我們要求您為世界買一棵樹,感謝我們的工作。 透過為 Treeware 森林做出貢獻,您將為當地家庭創造就業機會並恢復野生動物棲息地。

非常感謝

感謝這些很棒的公司對開源開發人員的支持 ❤

Travis CI SauceLabs Coveralls