CircleCI Orbsを使って、Vitestのテストをシンプルに実装する

CircleCI Orbsを使って、Vitestのテストをシンプルに実装する

Article actions
View in Markdown

Requires Chrome (latest) built-in AI.

Requires Chrome (latest) built-in AI.

AIコーディングが広まる中、コードレビューや自動テストなどの品質評価フェーズへの注目が高まりつつあります。今回は CircleCI で Vitestによるユニットテストを実行するケースを例に、できるだけ少ない設定コードで効果的なワークフローやレポートを得る方法を紹介します。

前提

Vite + TypeScript プロジェクトが既にあり、GitHub リポジトリに push すると CircleCI が動く状態になっているものとします。とはいえこのプロジェクトは、npm create viteでセットアップした直後の、シンプルなTypeScriptプロジェクトを想定しています。

% npm create vite

> first-cci-app@0.0.0 npx
> "create-vite"

│
◇  Project name:
│  first-cci-app
│
◇  Select a framework:
│  Vanilla
│
◇  Select a variant:
│  TypeScript
│
◇  Use rolldown-vite (Experimental)?:
│  No
│
◇  Install with npm and start now?
│  No
│
◇  Scaffolding project in /Users/hidetaka/sandboxes/first-cci-app/...
│
└  Done. Now run:

  cd tmp
  npm install
  npm run dev

ViteアプリにVitestで結合テストを導入する

Viteでセットアップしたばかりのアプリなので、ユニットテストをかける純粋関数がありません。そこで今回はVitestやJSDOMを利用した簡単な結合テストを実装してみましょう。

Step 1 – Vitest を導入する

まずはVitestとJSDOMなどの関連ライブラリを追加します。

npm install -D vitest @vitest/ui jsdom

続いてpackage.jsonscriptsにVitestを実行するコマンドを追加しましょう。CIやAIコーディングで利用する1回限りの実行コマンドと、人間がローカルで開発することを想定したWatchモードの2つを追加しておきます。

{
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "test": "vitest run",
    "test:watch": "vitest"
  }
}

Step 2 – TypeScript と Vitest の型設定

続いて TypeScript の設定を行いましょう。tsconfig.json に Vitest の型を追加しておきます。

{
  "compilerOptions": {
    // ...
    "types": ["vite/client", "vitest/globals"]
  },
  "include": ["src"]
}

これで、describeitexpect などを TypeScript で型エラーなく使えるようになります。

その後、vite.config.ts を更新しておきましょう。

import { defineConfig } from 'vite'

export default defineConfig({
  test: {
    globals: true,
    environment: 'jsdom',
    exclude: ['**/node_modules/**', '**/dist/**', '**/e2e/**'],
    reporters: ['verbose', 'junit'],
    outputFile: {
      junit: 'test-results/junit.xml',
    },
  },
})

globals: true を指定すると、describeitexpect をグローバルに使えるようになります。environment: 'jsdom' は、document.createElement など DOM を触るテスト用の設定です。

また、reporters: ['verbose', 'junit']outputFile.junit を追加しています。これはあとで紹介するCircleCIでテスト結果をチェックするために、テスト結果をJUnit XML として test-results/junit.xml に出力する設定です。

Step 3 – シンプルなテストを追加する

準備が整ったので、簡単なテストを実装しましょう。npm create viteでセットアップされりプロジェクトには、src/counter.tssetupCounterという関数が用意されています。この関数に対するテストを、 src/counter.test.ts として追加してみましょう。

// src/counter.test.ts
import { describe, it, expect, beforeEach } from 'vitest'
import { setupCounter } from './counter'

describe('setupCounter', () => {
  let button: HTMLButtonElement

  beforeEach(() => {
    button = document.createElement('button')
    document.body.appendChild(button)
  })

  it('初期状態でカウントが0と表示される', () => {
    setupCounter(button)
    expect(button.innerHTML).toBe('count is 0')
  })

  it('クリックするとカウントが1増える', () => {
    setupCounter(button)
    button.click()
    expect(button.innerHTML).toBe('count is 1')
  })

  it('複数回クリックするとカウントが正しく増える', () => {
    setupCounter(button)
    button.click()
    button.click()
    button.click()
    expect(button.innerHTML).toBe('count is 3')
  })

  it('カウンターは独立して動作する', () => {
    const button1 = document.createElement('button')
    const button2 = document.createElement('button')
    document.body.appendChild(button1)
    document.body.appendChild(button2)

    setupCounter(button1)
    setupCounter(button2)

    button1.click()
    button1.click()
    button2.click()

    expect(button1.innerHTML).toBe('count is 2')
    expect(button2.innerHTML).toBe('count is 1')
  })
})

このテストコードが動くかどうかをテストしてみましょう。

npm run test

テスト結果はCLI画面だけでなく、test-results/junit.xml としても出力されます。これはCircleCIのパイプラインにて都度読み込みさせるファイルですので、.gitignoretest-results/を追加して除外しておきましょう。

Step 4 – CircleCI のジョブにユニットテストを追加する

テストコードの準備もできましたので、CircleCIのパイプラインで実行するようにしましょう。

.circleci/config.ymlファイルを作成し、以下のコードを追加しましょう。

version: 2.1
orbs:
  node: circleci/node@7.2.1

workflows:
  test:
    jobs:
      - node/test:
          name: integration_test
          test-results-path: test-results

とてもシンプルな定義になりました。これはCircleCIが提供するジョブやコマンドをまとめた仕組み「CircleCI Orb」から、Node.jsアプリ向けのOrbであるcircleci/nodeを利用しているためです。このOrbを利用することで、npm installやインストール時のキャッシュ管理、そしてテスト実行時の制御やテスト実行結果の保存などのステップを、CircleCI側が提供したジョブ定義に基づいて実行できます。

test-results-pathは、Vitest実行時に生成された junit.xmlが保存されるディレクトリを指定します。これによって中の junit.xml を CircleCI が自動検出して、テストタブに表示してくれます。

念の為、CircleCI Local CLIを利用して設定ファイルにミスがないかもチェックしておきましょう。

% circleci config validate                    
Config file at .circleci/config.yml is valid.

これで CircleCIを利用したパイプラインの準備が完了しました。あとはGitでcommitし、githubへpushしておきましょう。

Step 5 – CircleCIのパイプラインで結果をチェックする

CircleCIとGitHubリポジトリの連携が完了していれば、このようにパイプラインが実行されます。

JUnitを利用したレポート出力設定を行っていると、Testタブにてテストの詳細がチェックできるようになります。ここをチェックすることで、プロジェクトのCI パイプラインが健全かどうかが簡単に確認できます。

時間のかかるテストや、失敗しがちなテストのレポートも見れます。もしCIパイプラインの完了時間が長いと感じることがあれば、これらのレポートをチェックして時間のかかっているテストがないかを調査しましょう。

CircleCI Orbsを活用して、巨人の肩を乗りこなそう

このように、CircleCIを利用したCIパイプラインの設定は、思っているよりも少ない設定で最大限の効果を得ることができます。自前でCIパイプラインの内容を設定するイメージが多いかもしれませんが、このようにCircleCIが提供するcircleci/XXXのOrbを活用することで、やりたいタスクの定義を非常にシンプルかつ少ないコードで実現できます。

AIコーディングの普及に伴い、生成されたコードの品質チェックを行うゲートウェイとしてCIパイプラインやDevOpsの注目度はこれからより高まると思われます。しかしCIパイプラインの設定や運用保守などは、差別化につながらない重労働であるともいえ、できるだけシンプルかつチームで保守性の高い構成を目指したいポイントです。

CircleCIの場合、CircleCIが提供するOrbsを活用することで、コマンドベースの設定ではなく「実現したいタスク内容」だけを定義する形でパイプラインを構築できます。また、CircleCIがOrbsとしてジョブ内容を保守するため、キャッシュ戦略などのベストプラクティスにも簡単に従うことができるのも便利です。

新しいCLIコマンドやツールを覚えるのは億劫になりがちですが、巡り巡って効率化につながる要素として、ぜひお試しください。

参考リンク

Share:

Hidetaka Okamoto profile photo

Hidetaka Okamoto

Business Development

I'm a Business Development professional at DigitalCube. Based on my experience in EC ASP development and as a Developer Advocate at Stripe, I'm working on methods to increase revenue for SaaS and EC sites, exploring efficiency improvements using generative AI, and developing new business models. You can follow me on Twitter at @hidetaka__dev

Related Articles

CircleCIでコーディングエージェントにCIエラーの修正指示を出す

AIコーディングにおいて、自動テストやCIサービスによる品質チェックは欠かすことのできない要件です。実行するたびに生成結果が変わる生成AIには、意図しない設計や実装・変更などが紛れ込むリスクがあり、それを回避するための安 […]

Vite アプリに E2E テストを実装し、CircleCI で自動実行するまで

Vite で構築した TypeScript アプリケーションに E2E テストを導入し、CircleCI で自動実行する環境を構築しました。本記事では、Playwright を使用した E2E テストの実装から、Circ […]

CircleCI MCPでCursor Rulesのルール違反をコミット前に検知する方法

CircleCI が提供する MCP サーバーには、git diff をベースにコーディング規約への準拠を確認する analyze_diff という機能があります。この機能を Cursor Rules と組み合わせること […]

CodeRabbit Proプランを CircleCI と連携して CI エラー修正を効率化する

2026年の年始休暇は、「スマホだけでどれだけ開発ができるか」に挑戦していました。その中で特にツラいなーと感じたのは、「作られたコードのデバッグ作業」です。この記事では、テストやビルドが失敗するタイプのデバッグ・調査作業 […]