テストは、堅牢なNode.jsアプリケーションを構築するための重要な部分です。適切なテストは、開発者が指摘する可能性のある多くの欠点を簡単に克服できます。 Node.js開発ソリューション 。
多くの開発者は単体テストで100%のカバレッジに焦点を合わせていますが、作成するコードを単独でテストするだけではないことが重要です。統合テストとエンドツーエンドテストは、アプリケーションの一部を一緒にテストすることで、その信頼性を高めます。これらの部分はそれ自体で問題なく機能する可能性がありますが、大規模なシステムでは、コードのユニットが個別に機能することはめったにありません。
Node.jsとMongoDBは一緒になって、最近最も人気のあるデュオの1つを形成しています。あなたがたまたまそれらを使用している多くの人々の一人であるなら、あなたは幸運です。
この記事では、複雑な環境や複雑なセットアップ/分解コードをセットアップすることなく、データベースの実際のインスタンスで実行されるNode.jsおよびMongoDBアプリケーションの統合テストとエンドツーエンドテストを簡単に作成する方法を学習します。 。
mongo-unitパッケージがNode.jsでの統合とエンドツーエンドのテストにどのように役立つかがわかります。 Node.js統合テストのより包括的な概要については、を参照してください。 この記事 。
通常、統合テストまたはエンドツーエンドテストの場合、スクリプトはテスト目的で実際の専用データベースに接続する必要があります。これには、すべてのテストケース/スイートの最初と最後に実行されるコードを記述して、データベースがクリーンで予測可能な状態にあることを確認することが含まれます。
aws認定ソリューションアーキテクト学習ガイド
これは一部のプロジェクトではうまく機能する可能性がありますが、いくつかの制限があります。
一方、実際のデータベースを使用すると、テスト環境が可能な限り本番環境に近くなります。これは、このアプローチの特別な利点と見なすことができます。
__________の設計原則を適用すると、関連するアイテムがグループ化されます。
テストに実際のデータベースを使用することには、いくつかの課題があるようです。しかし、実際のデータベースを使用することの利点は、あまりにも優れているため、受け継ぐことはできません。どうすれば課題を回避し、アドバンテージを維持できますか?
別のプラットフォームの優れたソリューションを再利用し、それをNode.jsの世界に適用することは、ここに進む方法です。
Javaプロジェクトは、この目的のためにインメモリデータベース(H2など)でDBUnitを広く使用しています。
DBUnitはJUnit(Javaテストランナー)と統合されており、各テスト/テストスイートなどのデータベース状態を定義できます。これにより、上記の制約がなくなります。
これらの概念から、Node.jsとMongoDBで同様のものを作成することにしました。 Mongo-unit 。
Mongo-unitは、NPMまたはYarnを使用してインストールできるNode.jsパッケージです。 MongoDBをメモリ内で実行します。 Mochaとうまく統合し、データベースの状態を管理するためのシンプルなAPIを提供することで、統合テストを簡単にします。
ライブラリは mongodb-ビルド済み NPMパッケージ。一般的なオペレーティングシステム用にビルド済みのMongoDBバイナリが含まれています。これらのMongoDBインスタンスは、メモリ内モードで実行できます。
プロジェクトにmongo-unitを追加するには、次のコマンドを実行できます。
npm install -D mongo-unit
または
コールオプションの価格設定方法
yarn add mongo-unit
そして、それだけです。このパッケージを使用するために、コンピューターにMongoDBをインストールする必要はありません。
タスクを管理するための単純なNode.jsアプリケーションがあると想像してみましょう。
// service.js const mongoose = require('mongoose') const mongoUrl = process.env.MONGO_URL || 'mongodb://localhost:27017/example' mongoose.connect(mongoUrl) const TaskSchema = new mongoose.Schema({ name: String, started: Date, completed: Boolean, }) const Task = mongoose.model('tasks', TaskSchema) module.exports = { getTasks: () => Task.find(), addTask: data => new Task(data).save(), deleteTask: taskId => Task.findByIdAndRemove(taskId) }
MongoDB接続URLはここではハードコーディングされていません。ほとんどのWebアプリケーションのバックエンドと同様に、環境変数から取得しています。これにより、テスト中に任意のURLに置き換えることができます。
const express = require('express') const bodyParser = require('body-parser') const service = require('./service') const app = express() app.use(bodyParser.json()) app.use(express.static(`${__dirname}/static`)) app.get('/example', (req, res) => { service.getTasks().then(tasks => res.json(tasks)) }) app.post('/example', (req, res) => { service.addTask(req.body).then(data => res.json(data)) }) app.delete('/example/:taskId', (req, res) => { service.deleteTask(req.params.taskId).then(data => res.json(data)) }) app.listen(3000, () => console.log('started on port 3000'))
これは、ユーザーインターフェイスを備えたサンプルアプリケーションのスニペットです。簡潔にするために、UIのコードは省略されています。あなたは完全な例をチェックすることができます GitHubで 。
Mochaにmongo-unitに対して統合テストを実行させるには、アプリケーションコードがNode.jsコンテキストにロードされる前に、mongo-unitデータベースインスタンスを実行する必要があります。これを行うには、mocha --require
を使用できますパラメータとMocha-prepareライブラリ。requireスクリプトで非同期操作を実行できます。
// it-helper.js const prepare = require('mocha-prepare') const mongoUnit = require('mongo-unit') prepare(done => mongoUnit.start() .then(testMongoUrl => { process.env.MONGO_URL = testMongoUrl done() }))
最初のステップは、テストをテストデータベース(testData.json
)に追加することです。
llc c corp vs s corp
{ 'tasks': [ { 'name': 'test', 'started': '2017-08-28T16:07:38.268Z', 'completed': false } ] }
次のステップは、テスト自体を追加することです。
const expect = require('chai').expect const mongoose = require('mongoose') const mongoUnit = require('../index') const service = require('./app/service') const testMongoUrl = process.env.MONGO_URL describe('service', () => { const testData = require('./fixtures/testData.json') beforeEach(() => mongoUnit.initDb(testMongoUrl, testData)) afterEach(() => mongoUnit.drop()) it('should find all tasks', () => { return service.getTasks() .then(tasks => { expect(tasks.length).to.equal(1) expect(tasks[0].name).to.equal('test') }) }) it('should create new task', () => { return service.addTask({ name: 'next', completed: false }) .then(task => { expect(task.name).to.equal('next') expect(task.completed).to.equal(false) }) .then(() => service.getTasks()) .then(tasks => { expect(tasks.length).to.equal(2) expect(tasks[1].name).to.equal('next') }) }) it('should remove task', () => { return service.getTasks() .then(tasks => tasks[0]._id) .then(taskId => service.deleteTask(taskId)) .then(() => service.getTasks()) .then(tasks => { expect(tasks.length).to.equal(0) }) }) })
そして、出来上がり!
セットアップとティアダウンを処理するコードが数行しかないことに注目してください。
ご覧のとおり、mongo-unitライブラリを使用して統合テストを作成するのは非常に簡単です。 MongoDB自体をモックすることはなく、同じMongooseモデルを使用できます。私たちはデータベースデータを完全に制御しており、テストのパフォーマンスをあまり損なうことはありません。 偽 MongoDBはメモリ内で実行されています。
これにより、統合テストに最適な単体テスト手法を適用することもできます。
ボーナスとして、mongo-unitに対してアプリケーション自体を実行することもできます。これにより、モックされたデータベースに対してアプリケーションのエンドツーエンドのテストを行うことができます。
エンドツーエンドのテストには、 Selenium WebDriver そして ハーマイオニーE2Eテストランナー 。
@media screen and(min-width 321px)and(max-width 480px)
まず、ドライバーとテストランナーをブートストラップします。
const mongoUnit = require('mongo-unit') const selenium = require('selenium-standalone') const Hermione = require('hermione') const hermione = new Hermione('./e2e/hermione.conf.js') //hermione config seleniumInstall() //make sure selenium is installed .then(seleniumStart) //start selenium web driver .then(mongoUnit.start) // start mongo unit .then(testMongoUrl => { process.env.MONGO_URL = testMongoUrl //store mongo url }) .then(() => { require('./index.js') //start application }) .then(delay(1000)) // wait a second till application is started .then(() => hermione.run('', hermioneOpts)) // run hermiona e2e tests .then(() => process.exit(0)) .catch(() => process.exit(1))
また、いくつかのヘルパー関数が必要になります(簡潔にするためにエラー処理は削除されています)。
function seleniumInstall() { return new Promise(resolve => selenium.install({}, resolve)) } function seleniumStart() { return new Promise(resolve => selenium.start(resolve)) } function delay(timeout) { return new Promise(resolve => setTimeout(resolve, timeout)) }
データベースにいくつかのデータを入力し、テストが完了したらデータベースをクリーンアップした後、最初のテストを実行できます。
const expect = require('chai').expect const co = require('co') const mongoUnit = require('../index') const testMongoUrl = process.env.MONGO_URL const DATA = require('./fixtures/testData.json') const ui = { task: '.task', remove: '.task .remove', name: '#name', date: '#date', addTask: '#addTask' } describe('Tasks', () => { beforeEach(function () { return mongoUnit.initDb(testMongoUrl, DATA) .then(() => this.browser.url('http://localhost:3000')) }) afterEach(() => mongoUnit.dropDb(testMongoUrl)) it('should display list of tasks', function () { const browser = this.browser return co(function* () { const tasks = yield browser.elements(ui.task) expect(tasks.length, 1) }) }) it('should create task', function () { const browser = this.browser return co(function* () { yield browser.element(ui.name).setValue('test') yield browser.element(ui.addTask).click() const tasks = yield browser.elements(ui.task) expect(tasks.length, 2) }) }) it('should remove task', function () { const browser = this.browser return co(function* () { yield browser.element(ui.remove).click() const tasks = yield browser.elements(ui.task) expect(tasks.length, 0) }) }) })
ご覧のとおり、エンドツーエンドのテストは統合テストと非常によく似ています。
統合とエンドツーエンドのテストは、大規模なアプリケーションにとって重要です。特にNode.jsアプリケーションは、自動テストから多大な恩恵を受けることができます。 mongo-unitを使用すると、そのようなテストに伴うすべての課題を心配することなく、統合テストとエンドツーエンドテストを作成できます。
発見できる 完全な例 GitHubでmongo-unitを使用する方法について説明します。
統合テストは、システムの複数のコンポーネントがさまざまなケースで正しく機能するかどうかを検証するために使用される自動テストです。
E2Eはエンドツーエンドの略で、一般的にエンドツーエンドのテストのコンテキストで使用されます。