Slackレポーター
wdio-slack-reporterはサードパーティパッケージです。詳細についてはGitHub | npmを参照してください。
WebdriverIOから、Incoming webhookとWeb APIを使用してSlackに結果を送信するレポーターです。
このパッケージはWebdriverIOバージョン6.x以上と互換性があります。
Slack通知スクリーンショット
 
WebdriverIO 4.x以前との互換性
このプロジェクトはWebdriverIOバージョン6.x以上と互換性があります。
4.x以前を使用している場合は、wdio-slack-reporterを使用してください。
インストール
最も簡単な方法は、`@moroo/wdio-slack-reporter`を`package.json`のdevDependencyとして保持することです。
{
  "devDependencies": {
    "@moroo/wdio-slack-reporter": "8.1.0"
  }
}
次のように簡単に実行できます。
- NPM
npm install @moroo/wdio-slack-reporter --save-dev
- Yarn
yarn add -D @moroo/wdio-slack-reporter
WebdriverIOのインストール方法については、こちらをご覧ください。
設定
wdio.conf.jsファイルの先頭に、以下を追加します。
ES6
// wdio.conf.js
import SlackReporter from '@moroo/wdio-slack-reporter';
レポーターを使用するには、wdio.conf.jsのreporters配列にslackを追加する必要があります。
// wdio.conf.js
export.config = {
  reporters: [
    [
      SlackReporter,
      {
        slackOptions: {
          type: 'web-api',
          channel: process.env.SLACK_CHANNEL || 'Cxxxxxxxxxx',
          slackBotToken: process.env.SLACK_BOT_TOKEN || 'xoxb-xxxxxxxxxx-xxxxxx...',
        },
      }
    ],
  ],
};
設定オプション
以下の設定オプションがサポートされています。通知を送信するには、`webhook`または`web-api`を設定する必要があります。`web-api`と`webhook`の両方が設定されている場合、`web-api`が使用されます。
Webhook (Incoming Webhook)
webhook (必須)
通知を送信するSlackチャンネルのIncoming Webhookです。URLが設定されていない場合、通知は送信されません。
- スコープ: `webhook`
- タイプ: `string`
slackName (オプション)
usernameの値は、Slack通知に送信者として表示されます。
- スコープ: `webhook`
- タイプ: `string`
- デフォルト: `"WebdriverIO Reporter"`
slackIconUrl (オプション)
Slackに表示するアイコンのURLです。
- スコープ: `webhook`
- タイプ: `string`
- デフォルト: `"https://webdriverio.dokyumento.jp/img/webdriverio.png"`
Web API (Slack Bot)
slackBotToken (必須)
通知を送信するSlackチャンネルのWeb APIです。ボットユーザーのトークンが必要です。ボットアクセストークンは常に`xoxb`で始まります。ボットトークンには、chat:write、files:writeのOAuthスコープが必要です。詳細については以下を参照してください。
- スコープ: `web-api`
- タイプ: `string`
channel (必須)
メッセージを送信するチャンネル、プライベートグループ、またはIMチャンネルです。エンコードされたIDまたは名前を使用できます。詳細については以下を参照してください。`チャンネルIDの探し方 - stackoverflow -`
- スコープ: `web-api`
- タイプ: `string`
uploadScreenshotOfFailedCase (オプション)
失敗したケースにスクリーンショットを添付するには、このオプションをtrueに設定します。
- スコープ: `web-api`
- タイプ: `boolean`
- デフォルト: `true`
notifyDetailResultThread (オプション)
このオプションは、notifyTestFinishMessageオプションがtrueの場合にのみ機能します。
Slackに投稿されたテスト結果の通知に、結果の詳細を含むスレッドを追加する場合は、このオプションをtrueに設定します。
- スコープ: `web-api`
- タイプ: `boolean`
- デフォルト: `true`
filterForDetailResults (オプション)
このオプションは、notifyDetailResultThreadオプションがtrueの場合にのみ機能します。
このオプションにフィルターを追加すると、Slackで詳細な結果がフィルター処理され、スレッドに送信されます。 (フィルターがない場合(配列が空または未定義)、すべてのフィルターが適用されます。) **フィルターリスト**: `passed`、`failed`、`pending`、`skipped`
- スコープ: `web-api`
- タイプ: `配列 (passed | failed | pending | skipped)`
- デフォルト: `['passed', 'failed', 'pending', 'skipped']`
createScreenshotPayload (オプション)
このオプションは、テストの失敗についてアップロードされるスクリーンショットのペイロードをカスタマイズします。
- スコープ: `web-api`
- タイプ: `function`
createResultDetailPayload (オプション)
このオプションは、テストの詳細な結果の通知に使用するペイロードをカスタマイズします。
- スコープ: `web-api`
- タイプ: `function`
共通
title (オプション)
このオプションをテストのタイトルに設定します。
- スコープ: `webhook`、`web-api`
- タイプ: `string`
resultsUrl (オプション)
テスト結果へのリンクを指定します。通知内ではクリック可能なリンクになります。
- スコープ: `webhook`、`web-api`
- タイプ: `string`
notifyTestStartMessage (オプション)
テスト開始の通知を送信するには、このオプションをtrueに設定します。
- スコープ: `webhook`、`web-api`
- タイプ: `boolean`
- デフォルト: `true`
notifyFailedCase (オプション)
Slackに報告されるテスト結果に失敗したケースを添付するには、このオプションをtrueに設定します。
- スコープ: `webhook`、`web-api`
- タイプ: `boolean`
- デフォルト: `true`
notifyTestFinishMessage (オプション)
テスト完了の通知を送信するには、このオプションをtrueに設定します。
- スコープ: `webhook`、`web-api`
- タイプ: `boolean`
- デフォルト: `true`
useScenarioBasedStateCounts (オプション) - Cucumberのみ
状態カウントをテスト(ステップ)ベースからシナリオベースに変更するには、このオプションをtrueに設定します。(Cucumberのみ)
- スコープ: `webhook`、`web-api`
- タイプ: `boolean`
- デフォルト: `false`
emojiSymbols (オプション)
このオプションは、デフォルトで設定されている絵文字セットを変更します。
- スコープ: `webhook`、`web-api`
- タイプ: `object`
- デフォルト
- passed - ✅ :white_check_mark:
- failed - ❌ :x:
- skipped - ⏸ :double_vertical_bar:
- pending - ❔ :grey_question:
- start - 🚀 :rocket:
- finished - 🏁 :checkered_flag:
- watch - ⏱ :stopwatch:
 
- passed - ✅ 
createStartPayload (オプション)
このオプションは、テスト開始時に通知されるペイロードをカスタマイズします。
- スコープ: `webhook`、`web-api`
- タイプ: `function`
createFailedTestPayload (オプション)
このオプションは、テストの失敗時に通知されるペイロードをカスタマイズします。
- スコープ: `webhook`、`web-api`
- タイプ: `function`
createResultPayload (オプション)
このオプションは、テストの結果を通知するペイロードをカスタマイズします。
- スコープ: `webhook`、`web-api`
- タイプ: `function`
Incoming Webhook の使用
Webhook を使用している場合、スレッド化とアップロードはできません。
そのため、upload と thread に関連する機能は使用できません。
設定例
// wdio.conf.js
import SlackReporter from "@moroo/wdio-slack-reporter";
export.config = {
  reporters: [
    [
      SlackReporter, {
        // Set the Slack Options used webhook.
        slackOptions: {
          type: 'webhook',
          webhook: process.env.SLACK_WEBHOOK_URL || "https://hooks.slack.com/........",
          slackName: "WebdriverIO Reporter",
          slackIconUrl: "https://webdriverio.dokyumento.jp/img/webdriverio.png",
        },
        // Set the Title of Test.
        title: 'Slack Reporter Test',
        // Set the Test Results URL.
        resultsUrl: process.env.JENKINS_URL,
        // Set the notification of Test Finished
        notifyTestFinishMessage: true,
        // Set the scenario-based state count (Only Cucumber)
        useScenarioBasedStateCounts: true,
        // Customize Slack Emoji Symbols.
        emojiSymbols: {
          passed: ':white_check_mark:',
          failed: ':x:',
          skipped: ':double_vertical_bar:',
          pending: ':grey_question:',
          start: ':rocket:',
          finished: ':checkered_flag:',
          watch: ':stopwatch:'
        },
        // Override the createStartPayload function.
        createStartPayload: function (runnerStats: RunnerStats): IncomingWebhookSendArguments {
          const payload: IncomingWebhookSendArguments = {
            // do something...
          }
          return payload;
        },
        // Override the createFailedTestPayload function.
        createFailedTestPayload: function (testStats: TestStats): IncomingWebhookSendArguments {
          const payload: IncomingWebhookSendArguments = {
            // do something...
          }
          return payload;
        },
        // Override the createResultPayload function.
        createResultPayload: function (runnerStats: RunnerStats, stateCounts: StateCount): IncomingWebhookSendArguments {
          const payload: IncomingWebhookSendArguments = {
            // do something...
          }
          return payload;
        }
      }
    ],
  ],
};
Web API の使用
API を使用するには、下記のようなスコープが必要です。
chat:write、files:write。詳細はこちらを参照してください。
設定例
// wdio.conf.js
import SlackReporter from "@moroo/wdio-slack-reporter";
export.config = {
  reporters: [
    [
      SlackReporter, {
        // Set the Slack Options used web-api.
        slackOptions: {
          type: 'web-api',
          slackBotToken: process.env.SLACK_BOT_TOKEN || "xoxb-xxxxxxxxxx-xxxxxx...",,
          channel: process.env.SLACK_CHANNEL || "Cxxxxxxxxxx",
          // Set this option to true to attach a screenshot to the failed case.
          uploadScreenshotOfFailedCase: true,
          // Set this option to true if you want to add thread with details of results to notification of test results posted to Slack.
          notifyDetailResultThread: true,
          // Set the Filter for detail results. (array is empty or undefined, all filters are applied.)
          filterForDetailResults: [
            'passed',
            'failed',
            'pending',
            'skipped'
          ],
          // Override the createScreenshotPayload function.
          createScreenshotPayload: function (testStats: TestStats, screenshotBuffer: Buffer): FilesUploadArguments {
            const payload: FilesUploadArguments = {
              // do something...
            }
            return payload;
          },
          // Override the createResultDetailPayload function.
          createResultDetailPayload: function (runnerStats: RunnerStats, stateCounts: StateCount): ChatPostMessageArguments {
            const payload: ChatPostMessageArguments = {
              // do something...
            }
            return payload;
          }
        },
        // Set the Title of Test.
        title: 'Slack Reporter Test',
        // Set the Test Results URL.
        resultsUrl: process.env.JENKINS_URL,
        // Set the notification of Test Finished
        notifyTestFinishMessage: true,
        // Set the scenario-based state count (Only Cucumber)
        useScenarioBasedStateCounts: true,
        // Customize Slack Emoji Symbols.
        emojiSymbols: {
          passed: ':white_check_mark:',
          failed: ':x:',
          skipped: ':double_vertical_bar:',
          pending: ':grey_question:',
          start: ':rocket:',
          finished: ':checkered_flag:',
          watch: ':stopwatch:'
        },
        // Override the createStartPayload function.
        createStartPayload: function (runnerStats: RunnerStats): IncomingWebhookSendArguments {
          const payload: IncomingWebhookSendArguments = {
            // do something...
          }
          return payload;
        },
        // Override the createFailedTestPayload function.
        createFailedTestPayload: function (testStats: TestStats): IncomingWebhookSendArguments {
          const payload: IncomingWebhookSendArguments = {
            // do something...
          }
          return payload;
        },
        // Override the createResultPayload function.
        createResultPayload: function (runnerStats: RunnerStats, stateCounts: StateCount): IncomingWebhookSendArguments {
          const payload: IncomingWebhookSendArguments = {
            // do something...
          }
          return payload;
        }
      }
    ],
  ],
};
対応API
getResultsUrl
型:
() => string | undefined
結果URLを取得します。
// getResultsUrl.spec.ts
import SlackReporter from '@moroo/wdio-slack-reporter';
describe('Get the resultsUrl value', function () {
  before(function () {
    const resultsUrl = SlackReporter.getResultsUrl();
    if (resultsUrl) {
      // do something...
    }
  });
  it('Do something', function () {
    // do something...
  });
});
setResultsUrl
型:
(url: string) => void
結果URLを設定します。
(テスト結果のURLが毎回変わる場合に便利です。)
// setResultsUrl.spec.ts
import SlackReporter from '@moroo/wdio-slack-reporter';
import { RESULTS_URL } from '../constants';
describe('Set the resultsUrl value', function () {
  before(function () {
    const resultsUrl = RESULTS_URL + new Date().toISOString();
    SlackReporter.setResultsUrl(resultsUrl);
  });
  it('Do something', function () {
    // do something...
  });
});
uploadFailedTestScreenshot
型:
(data: string | Buffer) => void
失敗したテスト通知にスクリーンショットをスレッドとして追加します。
(Webhook を使用している場合、警告が表示され、何も実行されません。)
// terminal console
WARN @moroo/slack-wdio-reporter: Not using web-api or disabled notifyFailedCase or uploadScreenshotOfFailedCase options.
// wdio.conf.js
export.config = {
  afterTest: async function (test, context, result) {
    if (error) {
      const result = await browser.takeScreenshot();
      SlackReporter.uploadFailedTestScreenshot(result);
    }
  }
}
postMessage
型:
(payload: ChatPostMessageArguments) => Promise<WebAPICallResult>
Slack にメッセージを投稿します。
(Webhook を使用している場合、エラーが発生します。)
// terminal console
ERROR @moroo/slack-wdio-reporter: Not using web-api.
// post.spec.ts
import SlackReporter, {
  ChatPostMessageArguments,
  WebAPICallResult,
} from '@moroo/wdio-slack-reporter';
describe('Post Function Test', function () {
  it('Post a message', async function () {
    const payload: ChatPostMessageArguments = {
      // do something...
    };
    const result: WebAPICallResult = await SlackReporter.post(payload);
  });
});
upload
型:
(payload: FilesUploadArguments) => Promise<WebAPICallResult>
Slack にファイルをアップロードします。
(Webhook を使用している場合、エラーが発生します。)
// terminal console
ERROR @moroo/slack-wdio-reporter: Not using web-api.
// upload.spec.ts
import SlackReporter, {
  FilesUploadArguments,
  WebAPICallResult,
} from '@moroo/wdio-slack-reporter';
describe('Upload Function Test', function () {
  it('Upload a files', async function () {
    const payload: FilesUploadArguments = {
      // do something...
    };
    const result: WebAPICallResult = await SlackReporter.upload(payload);
  });
});
send
型:
(payload: IncomingWebhookSendArguments) => Promise<IncomingWebhookResult>
Slack にメッセージを送信します。
(Web API を使用している場合、エラーが発生します。)
// terminal console
ERROR @moroo/slack-wdio-reporter: Not using webhook.
// send.spec.ts
import SlackReporter, {
  IncomingWebhookSendArguments,
  IncomingWebhookResult,
} from '@moroo/wdio-slack-reporter';
describe('Sand Function Test', function () {
  it('Send a message', async function () {
    const payload: IncomingWebhookSendArguments = {
      // do something...
    };
    const result: IncomingWebhookResult = await SlackReporter.send(payload);
  });
});
スクリーンショットの追加
失敗したテスト通知にスクリーンショットをスレッドとして追加するには、スクリーンショットを撮影した後、uploadFailedTestScreenshot 関数を使用してください。
// wdio.conf.js
export.config = {
  afterTest: async function (test, context, result) {
    if (error) {
      const result = await browser.takeScreenshot();
      SlackReporter.uploadFailedTestScreenshot(result);
    }
  }
}
既知の問題
非同期化
次のエラーが発生した場合は、wdio.conf.js で reporterSyncInterval、reporterSyncTimeout を設定してください。
ERROR @wdio/runner: Error: Some reporters are still unsynced: SlackReporter
//wdio.conf.js
export.config = {
  //
  // Determines in which interval the reporter should check if they are synchronized if they report their logs asynchronously (e.g. if logs are streamed to a 3rd party vendor).
  reporterSyncInterval: 500,
  // Determines the maximum time reporters have to finish uploading all their logs until an error is being thrown by the testrunner.
  reporterSyncTimeout: 20000,
}
Jasmine オプション - expectationResultHandler
ここに uploadFailedTestScreenshot 関数を追加しても機能しません。
これは、関数がテストのたびに実行されるため、現在のテストが不明であるためです。
// wdio.conf.js
export.config = {
  jasmineOpts: {
    // Jasmine default timeout
    defaultTimeoutInterval: 60000,
    //
    // The Jasmine framework allows interception of each assertion in order to log the state of the application
    // or website depending on the result. For example, it is pretty handy to take a screenshot every time
    // an assertion fails.
    expectationResultHandler: function (passed, assertion) {
      if (passed) {
        return;
      }
      /*
        Adding the uploadFailedTestScreenshot function here doesn't work either.
        This is because the function works after every test, so the current test is unknown.
        [x] const result = await browser.takeScreenshot();
        [x] SlackReporter.uploadFailedTestScreenshot(result);
      */
    },
  },
  // Add it here.
  afterTest: async function (test, context, result) {
    if (result.error) {
      const result = await browser.takeScreenshot();
      SlackReporter.uploadFailedTestScreenshot(result);
    }
  }
}