---
title: "Cypress E2Eテストの使い方｜インストールからcy.intercept・CI実行まで【Cypress 16対応】"
url: "https://www.issoh.co.jp/tech/details/7715/"
published: 2025-07-15
updated: 2026-10-02
categories: ["テスト"]
publisher: "株式会社一創"
---

# Cypress E2Eテストの使い方｜インストールからcy.intercept・CI実行まで【Cypress 16対応】

Cypress（サイプレス）は、テストコードをアプリと同じブラウザの中で動かすJavaScript／TypeScript製のE2Eテストフレームワークです。本体はMITライセンスで無料です。この記事では、2026年9月29日公開の最新版Cypress 16.1.1を使い、インストールからテストの書き方、APIのモック、ログインの共通化、GitHub Actionsでの実行までを順に説明します。

掲載コードは、検証用の小さなWebアプリに対してCypress 16.1.1とChrome 154で実行し、全件パスすることを確認したものです。Cypress 16では `Cypress.env()` と `cy.exec()` が削除されたため、2025年以前の解説記事のコードはそのままでは動かない箇所があります。

## まとめ：Cypress 16でE2Eテストを始めるときの要点

- 最新版は16.1.1（2026年9月29日）です。16.0.0（2026年9月1日）でNode.js 20のサポートが終わり、Node.js 22・24・26以上が必須になりました。
- npm 12は依存パッケージのpostinstallを既定でブロックするため、`npm install cypress` だけではバイナリが入りません。`npm install-scripts approve cypress` で許可してから `npm rebuild cypress` を実行します。
- テストは `describe`・`it` の中で `cy.visit`・`cy.get`・`should` をつなげて書きます。要素は `data-cy` 属性で指定します。
- 待ち時間は固定ミリ秒の `cy.wait(3000)` で書かず、コマンドの自動リトライ（既定4秒）と `cy.intercept` の別名待ちに任せます。
- ログインは `cy.session` でキャッシュし、パスワードやAPIキーは `cy.env()` で読みます。
- CIは公式の `cypress-io/github-action@v7` を使います。動画の録画はCloudなしでもできます。テストを複数マシンへ自動で振り分ける並列実行とTest ReplayはCypress Cloudの機能で、無料のStarterプランは月500テスト結果までです。
- 別タブの操作、2つのブラウザの同時操作、Python・Javaでのテスト記述が必要な場合はPlaywrightやSeleniumの方が向いています。

## Cypressの仕組みとPlaywright・Seleniumとの違い

Seleniumは、ブラウザの外からW3C WebDriverプロトコルで命令を送ります。Cypressはテストコードをアプリと同じブラウザの中で実行します。公式のTrade-offsページも「Cypress commands run inside of a browser」と説明しています。そのためDOMを直接読め、`cy.intercept` で通信を書き換えられ、テストランナーのコマンドログで各ステップ時点の画面に戻って確認できます。

### コマンドの自動リトライと既定4秒のタイムアウト

`cy.get` や `cy.contains` などのクエリは、後ろに続くアサーションが通るまで要素の取得をやり直します。待つ上限は設定の `defaultCommandTimeout` で、既定値は4000ミリ秒です。描画が遅い要素があっても、固定時間の待機は要りません。足りない箇所だけ `cy.get('[data-cy=list]', { timeout: 10000 })` のように個別に延ばします。

### Playwright・Seleniumとの比較

| 項目       | Cypress 16                      | Playwright              | Selenium 4               |
| -------- | ------------------------------- | ----------------------- | ------------------------ |
| テストの実行場所 | ブラウザの中                          | ブラウザの外                  | ブラウザの外（WebDriver）        |
| テストの記述言語 | JavaScript・TypeScript           | JS・TS・Python・Java・.NET  | Java・Python・C#・Ruby・JSなど |
| 対応ブラウザ   | Chrome・Edge・Firefox（WebKitは実験的） | Chromium・Firefox・WebKit | 主要ブラウザ                   |
| 別タブの操作   | @cypress/puppeteerが必要           | 標準で可                    | 標準で可                     |
| 並列実行     | Cypress Cloudで分散                | 標準（workers）             | Selenium Grid            |
| ライセンス    | MIT                             | Apache-2.0              | Apache-2.0               |

Playwrightの現行版と更新履歴は[Playwrightの最新バージョンは1.63｜確認・更新方法とリリース履歴【2026年9月】](/tech/details/9257/)、WebDriverの仕組みは[Seleniumとは？WebDriverの仕組みと4系の実行手順・ツール選定を解説](/tech/details/17435/)で扱っています。

### Cypressを選ばない方がよい場面

公式Trade-offsが恒久的な制約として挙げているのは、2つのブラウザを同時に動かせないこと、ブラウザの外の処理には `cy.task` やHTTP経由の `cy.request` を使うこと、などです。チャットのように2人のユーザーの画面を同時に操作して検証するテストはCypressでは書けません。iPhoneのSafariでの動作が品質の要になる案件も、WebKit対応が実験的な段階なので不向きです。テストを書くのがPythonやJavaのチームなら、記述言語の制約だけでPlaywrightかSeleniumを選んでかまいません。逆に、社内向けの業務Webアプリやシングルページアプリを、フロントエンドのエンジニア自身がJavaScriptで検証する体制なら、失敗した操作をコマンドログで追え、描画待ちを自動リトライに任せられるCypressが合います。

## Cypress 16のインストール手順と動作要件

### 動作要件：Node.js 22・24・26以上

Cypress 16.1.1の `package.json` の `engines` は `^22.0.0 || ^24.0.0 || >=26.0.0` です。Node.js 20と奇数版の25では動きません。OSはmacOS 13.5以上、Ubuntu 22.04以上（arm64は24.04以上）、Debian 12以上（arm64は13以上）、Windows 10・11（x64）、Windows Server 2019・2022・2025が対象です。ブラウザはChrome・Edge・Firefoxそれぞれの最新3メジャー版をサポートします。

### npm 12でCypressのバイナリが入らない問題

Cypressは、npmパッケージとは別に約数百MBのアプリ本体（バイナリ）を `postinstall` スクリプトでダウンロードします。npm 12.2.0で `npm install cypress --save-dev` を実行すると「install scripts blocked because they are not covered by allowScripts」という警告が出て、バイナリはダウンロードされません。公式の手順は次の3行です。

```
npm install cypress --save-dev
npm install-scripts approve cypress --no-allow-scripts-pin
npm rebuild cypress
```

`--no-allow-scripts-pin` を付けないと、`package.json` の `allowScripts` に `"cypress@16.1.1": true` とバージョン付きで記録されます。この状態で16.2に上げると、許可の対象外になって再びブロックされます。npm 11.16から11系の最後までは警告だけでバイナリは入ります。npm 11.17.0の警告に表示されるコマンドは `npm approve-scripts` で、npm 12でも同じ名前で使えます。許可リストを触りたくない場合は、インストール後に `npx cypress install` でバイナリだけを取得する方法もあります。

### cypress openでの初回起動と設定ファイル

```
npx cypress open
```

初回はLaunchpadという画面が開きます。「E2E Testing」を選ぶと `cypress.config.js`、サポートファイル、サンプルのフィクスチャが生成されます。テストファイル（spec）は既定で `cypress/e2e/**/*.cy.{js,jsx,ts,tsx}` に一致するものが読み込まれます。設定ファイルは `cypress.config.ts` にすればTypeScriptで書けます。古い記事に出てくる `cypress.json` はCypress 10で廃止されました。

## 最初のE2Eテストの書き方：describe・it・cy.visit・should

例として、メールアドレスとパスワードを入れてダッシュボードへ進むログイン画面をテストします。以下は専用の検証アプリ向けの例です。実行前に `localhost:3000` でアプリを起動し、テストユーザーと環境変数 `CYPRESS_password` を用意します。`data-cy` 属性・APIのパス・Cookie名は、対象アプリに合わせて書き換えてください。まず設定ファイルに `baseUrl` を書きます。これで `cy.visit('/')` のように相対パスで開けます。

```
const { defineConfig } = require('cypress')

module.exports = defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000',
  },
})
```

テストは `cypress/e2e/login.cy.js` に書きます。

```
describe('ログイン画面', () => {
  beforeEach(() => {
    cy.visit('/')
  })

  it('正しい認証情報でダッシュボードへ遷移する', () => {
    cy.env(['password']).then(({ password }) => {
      cy.get('[data-cy=email]').type('user@example.com')
      cy.get('[data-cy=password]').type(password, { log: false })
    })
    cy.get('[data-cy=submit]').click()
    cy.location('pathname').should('eq', '/dashboard')
    cy.contains('h1', 'ダッシュボード')
  })

  it('パスワードが違うとエラーを表示する', () => {
    cy.get('[data-cy=email]').type('user@example.com')
    cy.get('[data-cy=password]').type('wrong-password')
    cy.get('[data-cy=submit]').click()
    cy.get('[data-cy=error]').should('be.visible')
  })
})
```

`describe` がテストのまとまり、`it` が1件のテストです。`context` は `describe` の別名で、条件ごとに入れ子を分けたいときに使います。`type(password, { log: false })` は、入力コマンドをコマンドログに表示しない指定です。画面上の値を隠す機能ではないため、録画への映り込みまで防ぐものではありません。`cy.contains('h1', 'ダッシュボード')` は見出しの文言そのものを検証しており、文言が変わればテストが落ちます。

### 要素の選び方：data-cy属性を優先する理由

公式のBest Practicesは、クラス名・ID・タグ名ではなく `data-cy` などのテスト専用属性で要素を選ぶよう勧めています。クラス名はCSSの変更で、IDはJavaScriptの都合で変わるため、見た目を直しただけでテストが壊れるからです。文言が仕様そのもので、変わったら落ちてほしい箇所に限って `cy.contains` を使います。

### beforeEachとテスト分離（testIsolation）

設定 `testIsolation` の既定値は `true` です。各テストの前に、ページを `about:blank` に戻し、全ドメインのCookie・`localStorage`・`sessionStorage` を消します。そのため画面を開く処理は `beforeEach` に置きます。片付けを `afterEach` に書く必要はなく、公式も状態のリセットは各テストの前に行うよう説明しています。注意点として、IndexedDBはテスト分離でも消えません。オフラインキャッシュなどでIndexedDBを使うアプリでは、テスト側で明示的に消去します。

## cy.interceptとfixtureファイルによるAPI応答のモック

APIの応答を固定すると、バックエンドのデータに左右されずに画面の表示を検証できます。フィクスチャは `cypress/fixtures/todos.json` に置きます。

```
[
  { "id": 1, "title": "請求書を送る" },
  { "id": 2, "title": "議事録を共有する" }
]
```

```
describe('ToDo一覧', () => {
  beforeEach(() => {
    cy.login('user@example.com')
  })

  it('APIの応答をフィクスチャで差し替える', () => {
    cy.intercept('GET', '/api/todos', { fixture: 'todos.json' }).as('getTodos')
    cy.visit('/dashboard')
    cy.wait('@getTodos')
    cy.get('[data-cy=todo-list] li')
      .should('have.length', 2)
      .first()
      .should('have.text', '請求書を送る')
  })

  it('実APIの応答をそのまま検証する', () => {
    cy.intercept('GET', '/api/todos').as('getTodos')
    cy.visit('/dashboard')
    cy.wait('@getTodos').its('response.statusCode').should('eq', 200)
    cy.get('[data-cy=todo-list] li').should('have.length', 1)
  })
})
```

`cy.intercept` は `cy.visit` より前に書きます。後に書くと、ページ読み込み直後のリクエストを取り逃します。`.as('getTodos')` で付けた別名を `cy.wait('@getTodos')` で待つと、応答が返るまでだけ待機します。2件目のテストのように応答を差し替えず、実際のステータスコードだけを確かめる使い方もできます。モックとスタブの使い分けやモックサーバーの方式は[APIモッキングとは？モックサーバーの方式選定と契約ドリフト対策を実装目線で解説](/tech/details/16308/)で整理しています。

Cypress 16から、Chrome・Chromium・Edgeではテストの通信をCypress経由ではなくブラウザ本来のネットワークで傍受します。HTTP/2・HTTP/3で通信するようになった一方で、`req.httpVersion` は `undefined` になり、傍受した応答から `content-encoding` ヘッダーが見えなくなりました。これらの値が取得できる前提のアサーションは、Chrome・Chromium・Edgeで失敗する可能性があります。Firefox・WebKit・Electronは従来の経路のままです。移行期間用に設定 `forceHttp1` で全ブラウザを従来経路に戻せますが、この設定は追加時点で非推奨扱いです。

## ログイン処理の共通化：cy.sessionとカスタムコマンド

すべてのテストでログイン画面を操作すると、その分だけ実行時間が延びます。ログイン画面そのものは前章の `login.cy.js` で検証し、ほかのテストはAPIでログインして結果をキャッシュします。`cypress/support/commands.js` にカスタムコマンドを定義します。`cypress/support/e2e.js` から `import './commands'` で読み込まれていることも確認します。

```
Cypress.Commands.add('login', (email) => {
  cy.session(email, () => {
    cy.env(['password']).then(({ password }) => {
      cy.request({
        method: 'POST',
        url: '/api/login',
        body: { email, password },
        log: false,
      })
    })
  }, {
    validate() {
      cy.getCookie('sid').should('exist')
    },
  })
})
```

`cy.session` は第1引数のIDごとに、Cookie・`localStorage`・`sessionStorage` を保存し、2回目以降は保存した値を戻します。`validate` はセッションの初回作成後と復元後に実行されます。復元後に失敗するとログイン処理をやり直しますが、初回作成直後に失敗した場合はテストが失敗します。Cypress 16では `cy.getCookie` もリトライするクエリになったため、`should('exist')` は既定4秒まで再試行します。この例はCookieの有無だけを確かめる簡略版です。実アプリでは、ログイン中のユーザー情報を返すAPIを `cy.request` で呼び、ステータス200を確かめる方が、サーバー側で失効したセッションも見抜けます。

## 環境変数と秘密情報：Cypress.env()廃止後のcy.envとCypress.expose

Cypress 16.0.0で `Cypress.env()` が削除されました。16.1.1で呼ぶと「Cypress.env() was removed in Cypress version 16.0.0」で始まる例外が出て、テストはその場で失敗します。代わりのAPIは2つあり、ブラウザに値を見せてよいかで使い分けます。

| API                | ブラウザへの露出  | 入れる値             | 値の渡し方                                  |
| ------------------ | --------- | ---------------- | -------------------------------------- |
| `cy.env()`         | 要求した値のみ取得 | パスワード・APIキー・トークン | `CYPRESS_*`・`cypress.env.json`・`--env` |
| `Cypress.expose()` | あり        | 機能フラグ・環境名・APIの版  | 設定の`expose`・`--expose`                 |

`cy.env()` はキーの配列を受け取り、値は `.then` で受け取る非同期のコマンドです。前章のコードは、CIで `CYPRESS_password` という環境変数を渡せばそのまま動きます。`Cypress.expose()` は同期的に値を返しますが、アプリ側のコードやブラウザ拡張からも見えるため、秘密情報には使いません。テスト単位の設定上書きに書いていた `env` キーも使えなくなっています。

## cypress runとGitHub ActionsでのCI実行

### cypress runの主なオプションと終了コード

```
npx cypress run --browser chrome --spec "cypress/e2e/login.cy.js"
```

`cypress run` は画面を出さずに全テストを実行します。`--browser` を省略すると同梱のElectronで動きますが、Electronはテスト用ブラウザとしてCypress 16で非推奨になり、将来のメジャー版で削除予定です。今から作るCIでは `--browser chrome` を明示しておくと、削除時に設定を直さずに済みます。既定の終了コードは失敗したテストの件数です。256件ちょうど失敗すると多くのシェルで0として扱われるため、CIでは `--posix-exit-codes` を付けて「失敗があれば1」に揃える方が安全です。

### GitHub Actionsのワークフロー例

```
name: Cypress Tests

on: push

jobs:
  cypress-run:
    runs-on: ubuntu-24.04
    steps:
      - name: Checkout
        uses: actions/checkout@v7
      - name: Cypress run
        uses: cypress-io/github-action@v7
        with:
          build: npm run build
          start: npm start
          wait-on: 'http://localhost:3000'
          browser: chrome
        env:
          CYPRESS_password: ${{ secrets.APP_PASSWORD }}
```

公式Actionは依存のインストールとキャッシュ、ビルド、サーバーの起動、`wait-on` に書いたURLの応答待ち、テスト実行までを1ステップで行います。2026年10月1日時点の最新タグはv7.4.6で、公式は `@v7` のようにメジャー版で指定するよう勧めています。パスワードはリポジトリのSecretsに入れて `CYPRESS_` 付きの環境変数で渡し、テストでは `cy.env()` で読みます。どのイベントで実行するかの設計は[GitHub Actionsのトリガー（on）｜イベント選定とbranches・pathsフィルタの設計](/tech/details/16923/)を参照してください。

### Cypress Cloudの料金と並列実行

Cypress Cloudは、実行結果の記録、失敗時の再生（Test Replay）、複数マシンへのテスト分散を担うクラウドサービスで、無料枠と有料プランがあります。`npx cypress run --record --key <記録キー> --parallel` で使います。料金ページ（2026年10月2日確認）では、無料のStarterが月500テスト結果まで、Teamは年払い799ドルから（月額表示67ドル）で、基本料金に年12万テスト結果を含み、追加分は別料金です。課金対象はCloudに記録したテスト結果で、スキップは数えず、同じテストのリトライはまとめて1件と数えます。100件を毎日5回、30日間記録すると月15,000件です。無料枠は個人の検証用と考えておくのが現実的です。

## Cypress 15から16へ上げるときに壊れる箇所

16.0.0の破壊的変更のうち、E2Eテストで影響が出やすいものを抜き出しました。公式の移行ガイドには、AIアシスタントに読ませるための移行用プロンプトも載っています。

| 変更点           | 15系まで                        | 16系での対応                     |
| ------------- | ---------------------------- | --------------------------- |
| Node.js       | 20以上                         | 22・24・26以上                  |
| Cypress.env() | 使用可                          | cy.env()かCypress.expose()   |
| cy.exec()     | 15.21.0で非推奨                  | 削除。cy.task()へ               |
| cy.end()      | 使用可                          | 削除。呼び出しを消すだけ                |
| cy.typeの打鍵間隔  | 既定10ms                       | 既定0ms                       |
| 表示判定          | 従来方式                         | `modern`方式が既定               |
| メモリ管理         | experimentalMemoryManagement | manageBrowserMemory（既定true） |
| Chrome系の通信    | Cypress経由                    | ブラウザ本来の経路                   |

打鍵間隔が0msになったことで、1文字ごとの入力イベントに頼る入力補完やバリデーションのテストが不安定になる場合があります。その場合は設定で `keystrokeDelay: 10` に戻せます。16.0.0には、Chrome・Edgeでの実行が途中で出力を止めて固まる不具合などがあり、16.1.0（2026年9月15日）で修正されました。16系へ上げるなら16.1.0以降を使います。コンポーネントテストではVite 8未満、Angular 21未満、Next.js 14のサポートも終わっています。コンポーネントテスト側の変更は[Cypressとは｜E2E・コンポーネントテストの仕組みとcy.mountの書き方](/tech/details/3725/)で扱っています。

## Cypressでよく出るエラーと対処

- **Timed out retrying after 4000ms: Expected to find element**：4秒以内に要素が見つかっていません。まずセレクタの綴りを確認し、描画が本当に遅いならそのコマンドだけ `timeout` を延ばします。
- **別オリジンへの遷移で失敗する**：1つのテストは1つのオリジンが前提です。外部の認証画面などに移る部分は `cy.origin()` で囲みます。`injectDocumentDomain` が無効（既定）のときは、同じドメインのサブドメインも別オリジンとして扱われます。
- **Cypress.env() was removed / cy.exec() was removed**：16系への更新で出ます。前者は `cy.env()` か `Cypress.expose()`、後者は `cy.task()` に書き換えます。プラグインが呼んでいる場合は、Cypress 16対応版へ更新します。
- **Cypress binary is missing**：バイナリが見つかりません。npm 12のpostinstallブロックのほか、ダウンロード失敗やキャッシュの欠落などが原因になります。`npx cypress install` の後、`npx cypress verify` で起動できるか確かめます。
- **アプリ側の例外でテストが落ちる**：アプリが投げた未処理の例外も、Cypressはテストの失敗として扱います。無視する場合は `Cypress.on('uncaught:exception', ...)` で、エラーメッセージを条件にして対象を絞ります。

## よくある質問

### Cypressの読み方は？

「サイプレス」と読みます。英語で糸杉を意味する単語で、検索結果に樹木や香水の情報が混じるのはそのためです。テストツールを調べるときは「cypress e2e」「cypress testing」のように用途の語を足すと絞れます。

### Cypressは無料で使えますか？

テストを書いて実行するCypress本体はMITライセンスで無料です。実行結果の記録や自動分散並列実行を担うCypress Cloudには無料枠と有料プランがあり、無料のStarterプランは月500テスト結果までです。

### PythonやC#でCypressのテストを書けますか？

書けません。テストコードはJavaScriptかTypeScriptで書きます。ただし、テスト対象のアプリはブラウザで動けばよく、バックエンドがPython・C#・PHPでも検証できます。テストもPythonやC#で書きたい場合はPlaywrightかSeleniumを選びます。

### cypress.jsonはどこへ行きましたか？

Cypress 10で廃止され、`cypress.config.js` または `cypress.config.ts` に置き換わりました。プラグインファイルの処理も、設定内の `setupNodeEvents` に移っています。

### E2Eテストとは何ですか？

ユーザーと同じようにブラウザを操作して、画面からサーバー、データベースまでを通しで検証するテストです。単体テストより遅く壊れやすいため、件数は主要な業務フローに絞ります。結合テストとの違いや対象の選び方は[E2E（エンドツーエンド）テストのベストプラクティス｜結合テストとの違いとツール選定](/tech/details/5470/)、テスト全体の配分は[テストピラミッドとは？単体・結合・E2Eの配分と実装者向けテスト戦略設計](/tech/details/13289/)で解説しています。

## 関連記事

- [Cypressとは｜E2E・コンポーネントテストの仕組みとcy.mountの書き方](/tech/details/3725/)
- [E2E（エンドツーエンド）テストのベストプラクティス｜結合テストとの違いとツール選定](/tech/details/5470/)
- [Playwrightの最新バージョンは1.63｜確認・更新方法とリリース履歴【2026年9月】](/tech/details/9257/)
- [Seleniumとは？WebDriverの仕組みと4系の実行手順・ツール選定を解説](/tech/details/17435/)
- [Page Object Model（POM）とは？Playwright・Seleniumの実装例と保守コストの実測](/tech/details/10677/)

---

出典: [Cypress E2Eテストの使い方｜インストールからcy.intercept・CI実行まで【Cypress 16対応】](<https://www.issoh.co.jp/tech/details/7715/>)（株式会社一創）
