0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CodeceptJS のテストフィルタ活用と ESLint カスタムルールによる安全対策

Posted at

はじめに

CodeceptJS では VitestPlaywright のように特定のテストケースやスイートのみを実行したり、一時的にスキップしたりするための簡単な記法が用意されています。
公式ドキュメントに基づいてテストのフィルタリング方法を整理します。
また、フィルタリングした内容が誤って残ってしまうのを防ぐため、ESLint のカスタムルールを適用する方法を紹介します。
※カスタムルールの詳細な仕様や、Linter を開発フローにどう組み込むかの運用のお話はしませんので、ご了承ください。

注意事項

記事掲載時点、CodeceptJS は ESModules にまだ対応していないようです。
Migrate CodeceptJS to ESM (Top-level await) · Issue #4185 · codeceptjs/CodeceptJS
そのため、本記事内のコードでは基本 ESModules の記法に統一していますが、
importrequire など、適宜プロジェクトの状況によって読み替えてください。

環境情報

OS: Windows 11
Visual Studio Code: 1.100.2
CodeceptJS: 3.7.3
ESLint: v9.27.0

CodeceptJS のテストフィルタリング

.only:特定のテストだけを実行

Scenario.only を使うと、そのテストだけが実行対象になります。

Feature("ログイン機能");

Scenario.only("正しい認証情報でログインできること", ({ I }) => {
  I.amOnPage("/login");
  I.fillField("ユーザー名","user1");
  I.fillField("パスワード","password");
  I.click("ログイン");
  I.see("ようこそ");
});

この例では、他の Scenario は無視され、このテストだけが実行されます。
特に修正した部分のみを実行して確認するのに有用です。

.skip:特定のテストをスキップ

Scenario.skip (xScenario) や Feature.skip (xFeature) を使うと、一時的にそのテストを無効化できます。

Feature("ログイン機能");

Scenario.skip("ログイン失敗時のエラーメッセージ", ({ I }) => {
  // 現在修正中なのでスキップ
});

.skip を使うと、コメントアウトよりも意図が明確になり、元に戻しやすくなります。
Feature.skip (xFeature)は CodeceptJS の v2.6.6 から

その他:grep によるフィルタリング(コマンドライン)

CodeceptJS のコマンドには --grep オプションがあり、シナリオ名にマッチするものだけを実行できます。

npx codeceptjs run --grep "ログイン"

Feature, Scenario 両方とも検索にヒットします。
正規表現も使えるため、柔軟にフィルタリングが可能です。

※特に正規表現で指定しない場合は部分一致になるようなので注意が必要です。
"ログインの機能" で検索した場合、"ログインの機能1"、"ログインの機能2" のいずれもヒットします。

ESLint カスタムルール

以下を目標として作成していきます。

  • Scenario.skip() と Scenario.only() の使用を検出して警告する
  • ESLint の自動修正機能でこれらを通常の Scenario() に変換する
  • プラグインとしては公開しない(ローカルでルールを適用するのに留める)

1. カスタムルールファイルを作成する

まず、ESLint のカスタムルールを格納するディレクトリとルールファイルを作成します。
 ./eslint-rules/no-scenario-skip-or-only.js

2. ルールのロジックを実装する

以下のコードを記述します。

no-scenario-skip-or-only.js
export default {
  meta: {
    type: 'suggestion',
    docs: {
      description: 'disallow Scenario.skip and Scenario.only in CodeceptJS tests',
      recommended: true,
      url: null
    },
    fixable: 'code',
    schema: [],
    messages: {
      noScenarioSkip: "Unexpected 'Scenario.skip()'. Remove '.skip' to run all tests.",
      noScenarioOnly: "Unexpected 'Scenario.only()'. Remove '.only' to run all tests."
    }
  },
  create(context) {
    return {
      MemberExpression(node) {
        if (
          node.object.name === 'Scenario' &&
          (node.property.name === 'skip' || node.property.name === 'only')
        ) {
          context.report({
            node,
            messageId: node.property.name === 'skip' ? 'noScenarioSkip' : 'noScenarioOnly',
            fix(fixer) {
              // '.skip' または '.only' 部分を削除
              return fixer.removeRange([node.object.range[1], node.range[1]]);
            }
          });
        }
      }
    };
  }
};

補足として、Scenario.skip の部分は、AST(抽象構文木) 上では MemberExpression として表現されます。

  • Scenario が「オブジェクト」
  • skip が「プロパティ」

ノードタイプやセレクタについて詳しくは公式ドキュメントを参照ください。

3. カスタムルールのテストを書く

カスタムルールのテストファイルを作成し、有効なテストケースと無効なテストケースに対してテストします。

no-scenario-skip-or-only.test.js
import { RuleTester } from 'eslint';
import rule from '../no-scenario-skip-or-only.js';

const ruleTester = new RuleTester();

ruleTester.run('no-scenario-skip-or-only', rule, {
  valid: ['Scenario("xxx", () => {} )'],
  invalid: [
    {
      code: 'Scenario.skip("xxx", () => {} )',
      errors: [{ messageId: 'noScenarioSkip' }],
      output: 'Scenario("xxx", () => {} )'
    },
    {
      code: 'Scenario.only("xxx", () => {} )',
      errors: [{ messageId: 'noScenarioOnly' }],
      output: 'Scenario("xxx", () => {} )'
    }
  ]
});
console.log('All tests passed!');

node eslint-rules/no-scenario-skip-or-only.test.js で実行します。
テストに合格するとコンソールに All tests passed! が出力されます。

4. ESLint 設定ファイルにカスタムルールを追加する

eslint.config.js ファイルを以下のように更新します(Flat Config 使用時)。

eslint.config.js
// ...
// カスタムルールを読み込み
import noScenarioSkipOrOnlyRule from './eslint-rules/no-scenario-skip-or-only.js';

// カスタムプラグインの定義
const codeceptRules = {
  plugins: {
    codecept: {
      rules: {
        'no-scenario-skip-or-only': noScenarioSkipOrOnlyRule
      }
    }
  }
};

export default [
  // ...
  codeceptRules, // カスタムプラグイン設定を追加
  {
    rules: {
      // カスタムルールを適用
      'codecept/no-scenario-skip-or-only': 'error'
    }
  },
];

※「カスタムプラグインの定義」の部分に関しては別途プラグイン用のファイルを作成することでルールを npm パッケージで共有し、他のプロジェクトで使用できるようになります。
 今回はローカルでの使用にとどめます。

5. ESLint を実際に実行して確認する

以下のような簡易的な CodeceptJS 用のテストファイルを作成します。
./sample.test.js
※意図的に Scenario.skip と Scenario.only を含めてルールが動作するか確認します。

sample.test.js
Feature('My First Test');

Scenario('test something', ({ I }) => {
  I.amOnPage('https://github.com');
  I.see('GitHub');
});

Scenario.skip('skip', () => {}); // 検出される

Scenario.only('only', () => {}); // 検出される

VS Code に ESLint の拡張機能を導入している場合は、この時点でエラーが検出されるとおもいます。
Pasted image 20250521060324.png

次のコマンドを実行してルールが機能するか確認します。
npx eslint sample.test.js

エラーメッセージが表示されれば、ルールが正常に機能しています。

sample.test.js:8:1: Unexpected 'Scenario.skip()'. Remove '.skip' to run all tests. codecept/no-scenario-skip-or-only

sample.test.js:10:1: Unexpected 'Scenario.only()'. Remove '.only' to run all tests. codecept/no-scenario-skip-or-only

6. 自動修正を試す

--fix オプションを付けて ESLint を実行すると、.skip と .only が自動的に削除されます。

npx eslint sample.test.js --fix

自動修正後、テストファイルは以下のように変わります。

sample.test.js
Feature('My First Test');

Scenario('test something', ({ I }) => {
  I.amOnPage('https://github.com');
  I.see('GitHub');
});

- Scenario.skip('skip', () => {});
+ Scenario('skip', () => {});

- Scenario.only('only', () => {});
+ Scenario('only', () => {});

まとめ

.only.skip を活用することで、テストの作成や確認を効率化できます。
また、カスタムルールをプロジェクトに追加することで、開発者が誤って Scenario.skip や Scenario.only を残してしまうミスを防止できます。※
※コミット時は Husky と lint-staged を、PRマージ時であれば CI/CD パイプラインに組み込むなど。

参考リンク

CodeceptJS公式ドキュメント:Skipping
Custom Rule Tutorial - ESLint - Pluggable JavaScript Linter

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?