apeescape2.com
  • メイン
  • デザイナーライフ
  • Uiデザイン
  • ブランドデザイン
  • バックエンド
技術

Node.jsとMongoDBで統合とエンドツーエンドのテストが簡単に

テストは、堅牢なNode.jsアプリケーションを構築するための重要な部分です。適切なテストは、開発者が指摘する可能性のある多くの欠点を簡単に克服できます。 Node.js開発ソリューション 。

多くの開発者は単体テストで100%のカバレッジに焦点を合わせていますが、作成するコードを単独でテストするだけではないことが重要です。統合テストとエンドツーエンドテストは、アプリケーションの一部を一緒にテストすることで、その信頼性を高めます。これらの部分はそれ自体で問題なく機能する可能性がありますが、大規模なシステムでは、コードのユニットが個別に機能することはめったにありません。

Node.jsとMongoDBは一緒になって、最近最も人気のあるデュオの1つを形成しています。あなたがたまたまそれらを使用している多くの人々の一人であるなら、あなたは幸運です。



この記事では、複雑な環境や複雑なセットアップ/分解コードをセットアップすることなく、データベースの実際のインスタンスで実行されるNode.jsおよびMongoDBアプリケーションの統合テストとエンドツーエンドテストを簡単に作成する方法を学習します。 。

mongo-unitパッケージがNode.jsでの統合とエンドツーエンドのテストにどのように役立つかがわかります。 Node.js統合テストのより包括的な概要については、を参照してください。 この記事 。

実際のデータベースの取り扱い

通常、統合テストまたはエンドツーエンドテストの場合、スクリプトはテスト目的で実際の専用データベースに接続する必要があります。これには、すべてのテストケース/スイートの最初と最後に実行されるコードを記述して、データベースがクリーンで予測可能な状態にあることを確認することが含まれます。

aws認定ソリューションアーキテクト学習ガイド

これは一部のプロジェクトではうまく機能する可能性がありますが、いくつかの制限があります。

  • テスト環境は非常に複雑になる可能性があります。データベースをどこかで実行し続ける必要があります。多くの場合、これにはCIサーバーをセットアップするための追加の作業が必要です。
  • データベースと操作は比較的遅くなる可能性があります。データベースはネットワーク接続を使用し、操作にはファイルシステムのアクティビティが必要になるため、何千ものテストをすばやく実行するのは簡単ではない場合があります。
  • データベースは状態を保持しているため、テストにはあまり便利ではありません。テストは互いに独立している必要がありますが、共通のDBを使用すると、1つのテストが他のテストに影響を与える可能性があります。

一方、実際のデータベースを使用すると、テスト環境が可能な限り本番環境に近くなります。これは、このアプローチの特別な利点と見なすことができます。

__________の設計原則を適用すると、関連するアイテムがグループ化されます。

実際のインメモリデータベースの使用

テストに実際のデータベースを使用することには、いくつかの課題があるようです。しかし、実際のデータベースを使用することの利点は、あまりにも優れているため、受け継ぐことはできません。どうすれば課題を回避し、アドバンテージを維持できますか?

別のプラットフォームの優れたソリューションを再利用し、それをNode.jsの世界に適用することは、ここに進む方法です。

Javaプロジェクトは、この目的のためにインメモリデータベース(H2など)でDBUnitを広く使用しています。

DBUnitはJUnit(Javaテストランナー)と統合されており、各テスト/テストスイートなどのデータベース状態を定義できます。これにより、上記の制約がなくなります。

  • DBUnitとH2はJavaライブラリであるため、追加の環境を設定する必要はありません。すべてJVMで実行されます。
  • インメモリデータベースにより、この状態管理が非常に高速になります。
  • DBUnitを使用すると、データベースの構成が非常に簡単になり、それぞれの場合にデータベースの状態を明確に保つことができます。
  • H2はSQLデータベースであり、MySQLと部分的に互換性があるため、ほとんどの場合、アプリケーションは本番データベースと同様にH2を使用できます。

これらの概念から、Node.jsとMongoDBで同様のものを作成することにしました。 Mongo-unit 。

Mongo-unitは、NPMまたはYarnを使用してインストールできるNode.jsパッケージです。 MongoDBをメモリ内で実行します。 Mochaとうまく統合し、データベースの状態を管理するためのシンプルなAPIを提供することで、統合テストを簡単にします。

ライブラリは mongodb-ビルド済み NPMパッケージ。一般的なオペレーティングシステム用にビルド済みのMongoDBバイナリが含まれています。これらのMongoDBインスタンスは、メモリ内モードで実行できます。

Mongoユニットのインストール

プロジェクトにmongo-unitを追加するには、次のコマンドを実行できます。

npm install -D mongo-unit

または

コールオプションの価格設定方法
yarn add mongo-unit

そして、それだけです。このパッケージを使用するために、コンピューターにMongoDBをインストールする必要はありません。

統合テストにMongoユニットを使用する

タスクを管理するための単純な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はメモリ内で実行されています。

これにより、統合テストに最適な単体テスト手法を適用することもできます。

  • 各テストを他のテストから独立させます。各テストの前に新しいデータをロードし、各テストで完全に独立した状態を提供します。
  • 各テストに最低限必要な状態を使用します。データベース全体にデータを入力する必要はありません。特定のテストごとに最低限必要なデータを設定するだけで済みます。
  • データベースに1つの接続を再利用できます。テストのパフォーマンスが向上します。

ボーナスとして、mongo-unitに対してアプリケーション自体を実行することもできます。これにより、モックされたデータベースに対してアプリケーションのエンドツーエンドのテストを行うことができます。

Seleniumを使用したエンドツーエンドのテスト

エンドツーエンドのテストには、 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は何の略ですか?

E2Eはエンドツーエンドの略で、一般的にエンドツーエンドのテストのコンテキストで使用されます。

Gulpを使用したJavaScript自動化の概要

Webフロントエンド

Gulpを使用したJavaScript自動化の概要
レガシーデータを台無しにせずに移行する

レガシーデータを台無しにせずに移行する

データサイエンスとデータベース

人気の投稿
在宅勤務におけるアンチパターン
在宅勤務におけるアンチパターン
スタートアップCFOの採用-CFOを採用する時期と必要な理由
スタートアップCFOの採用-CFOを採用する時期と必要な理由
スマートウォッチの開発:スマートウォッチは問題に値するか?
スマートウォッチの開発:スマートウォッチは問題に値するか?
ルーツスタックを使用した最新のWordPress開発ワークフロー
ルーツスタックを使用した最新のWordPress開発ワークフロー
コミュニケーションディレクター
コミュニケーションディレクター
 
レガシーデータを台無しにせずに移行する
レガシーデータを台無しにせずに移行する
計算写真におけるPython画像処理の概要
計算写真におけるPython画像処理の概要
AppleM1プロセッサの概要と互換性
AppleM1プロセッサの概要と互換性
オープンソースソフトウェア-ビジネスモデルは収益性があるかどうか?
オープンソースソフトウェア-ビジネスモデルは収益性があるかどうか?
あなたのためにリモートワークを機能させる方法
あなたのためにリモートワークを機能させる方法
人気の投稿
  • メモリリークの原因となるもの
  • ユーザー数によるアプリのデート
  • LLCとはどのような種類の企業ですか
  • ポーターの5つの力のスイッチングコスト
  • データの視覚化を作成する方法
  • コンサルタントの時給と給与
カテゴリー
設計プロセス 分散チーム Kpiと分析 計画と予測 Webフロントエンド トレンド リモートの台頭 革新 プロセスとツール エンジニアリング管理

© 2021 | 全著作権所有

apeescape2.com