Jest هي مكتبة لاختبار كود JavaScript. إنه مشروع مفتوح المصدر تتم صيانته بواسطة Facebook ، وهو مناسب بشكل خاص لاختبار كود React ، على الرغم من أنه لا يقتصر على ذلك: يمكنه اختبار أي كود JavaScript. Jest سريع جدا وسهل الاستخدام
- مقدمة في Jest
- تثبيت
- أنشئ اختبار Jest الأول
- قم بتشغيل Jest باستخدام رمز VS
- المطابقون
- يثبت
- تمزيق
- مجموعة الاختبارات باستخدام وصف ()
- اختبار الكود غير المتزامن
- السخرية
- اختبار اللقطة
مقدمة في Jest
Jest هي مكتبة لاختبار كود JavaScript.
إنه مشروع مفتوح المصدر تتم صيانته بواسطة Facebook ، وهو مناسب بشكل خاص لاختبار كود React ، على الرغم من أنه لا يقتصر على ذلك: يمكنه اختبار أي كود JavaScript. قوتها هي:
- إنه سريع
- يمكن أن تؤدياختبار لقطة
- إنه برأي ، ويقدم كل شيء خارج الصندوق دون مطالبتك بالاختيار
Jest هي أداة تشبه إلى حد بعيد Mocha ، على الرغم من وجود اختلافات بينهما:
- Mocha أقل رأيًا ، بينما Jest لديها مجموعة معينة من الاتفاقيات
- يتطلب Mocha مزيدًا من التكوين ، بينما يعمل Jest عادةً خارج الصندوق ، وذلك بفضل الرأي
- Mocha أقدم وأكثر رسوخًا ، مع المزيد من تكامل الأدوات
في رأيي ، فإن أكبر ميزة لـ Jest هي أنه حل خارج الصندوق يعمل دون الحاجة إلى التفاعل مع مكتبات اختبار أخرى لأداء وظيفته.
تثبيت
يتم تثبيت Jest تلقائيًا فيcreate-react-app
، لذلك إذا كنت تستخدم ذلك ، فلن تحتاج إلى تثبيت Jest.
يمكن تثبيت Jest في أي مشروع آخر باستخدامغزل:
yarn add --dev jest
أوnpm:
npm install --save-dev jest
لاحظ كيف نوجه كلاهما لوضع Jest فيdevDependencies
جزء منpackage.json
الملف ، بحيث يتم تثبيته فقط في بيئة التطوير وليس في الإنتاج.
أضف هذا السطر إلى جزء البرامج النصية من ملفpackage.json
ملف:
{
"scripts": {
"test": "jest"
}
}
بحيث يمكن إجراء الاختبارات باستخدامyarn test
أوnpm run test
.
بدلاً من ذلك ، يمكنك تثبيت Jest عالميًا:
yarn global add jest
وقم بإجراء جميع اختباراتك باستخدام ملفjest
أداة سطر الأوامر.
أنشئ اختبار Jest الأول
تم إنشاء المشاريع باستخدامcreate-react-app
تثبيت Jest وتكوينه مسبقًا خارج الصندوق ، ولكن إضافة Jest إلى أي مشروع أمر سهل مثل الكتابة
yarn add --dev jest
أضف إلى ملفpackage.json
هذا الخط:
{
"scripts": {
"test": "jest"
}
}
وإجراء الاختبارات الخاصة بك عن طريق التنفيذyarn test
في قوقعتك.
الآن ، ليس لديك أي اختبارات هنا ، لذلك لن يتم تنفيذ أي شيء:
لنقم بإنشاء الاختبار الأول. افتحmath.js
ملف واكتب دالتين سنختبرهما لاحقًا:
const sum = (a, b) => a + b
const mul = (a, b) => a * b
const sub = (a, b) => a - b
const div = (a, b) => a / b
module.exports = { sum, mul, sub, div }
الآن قم بإنشاء ملفmath.test.js
في نفس المجلد ، وهناك سنستخدم Jest لاختبار الوظائف المحددة فيmath.js
:
const { sum, mul, sub, div } = require('./math')
test(‘Adding 1 + 1 equals 2’, () => {
expect(sum(1, 1)).toBe(2)
})
test(‘Multiplying 1 * 1 equals 1’, () => {
expect(mul(1, 1)).toBe(1)
})
test(‘Subtracting 1 - 1 equals 0’, () => {
expect(sub(1, 1)).toBe(0)
})
test(‘Dividing 1 / 1 equals 1’, () => {
expect(div(1, 1)).toBe(1)
})
ادارةyarn test
يؤدي إلى تشغيل Jest على جميع ملفات الاختبار التي يعثر عليها ، وإرجاع النتيجة النهائية إلينا:
قم بتشغيل Jest باستخدام رمز VS
يعد Visual Studio Code محررًا رائعًا لتطوير JavaScript. التمديد الدعابةتقدم تكاملاً من الدرجة الأولى لاختباراتنا.
بمجرد تثبيته ، سيكتشف تلقائيًا ما إذا كنت قد قمت بتثبيت Jest في devDependency الخاص بك وتشغيل الاختبارات. يمكنك أيضًا استدعاء الاختبارات يدويًا عن طريق تحديد ملفدعابة: ابدأ عداءيأمر. سيتم تشغيل الاختبارات والبقاء في وضع المراقبة لإعادة تشغيلها كلما قمت بتغيير أحد الملفات التي تحتوي على اختبار (أو ملف اختبار):
المطابقون
في المقال السابق استخدمتهtoBe()
كالوحيدالمطابق:
test('Adding 1 + 1 equals 2', () => {
expect(sum(1, 1)).toBe(2)
})
المطابق هو طريقة تتيح لك اختبار القيم.
المطابقات الأكثر استخدامًا ، مقارنة قيمة نتيجةexpect()
بالقيمة التي تم تمريرها كوسيطة ، هي:
toBe
يقارن المساواة الصارمة ، باستخدام===
toEqual
يقارن قيم متغيرين. إذا كان كائنًا أو مصفوفة ، فإنه يتحقق من تساوي جميع الخصائص أو العناصرtoBeNull
يكون صحيحًا عند تمرير قيمة فارغةtoBeDefined
يكون صحيحًا عند تمرير قيمة محددة (عكس ما ورد أعلاه)toBeUndefined
يكون صحيحًا عند تمرير قيمة غير محددةtoBeCloseTo
يستخدم لمقارنة القيم العائمة وتجنب أخطاء التقريبtoBeTruthy
صواب إذا تم اعتبار القيمة صحيحة (مثلif
يفعل)toBeFalsy
صواب إذا تم اعتبار القيمة خاطئة (مثلif
يفعل)toBeGreaterThan
صحيح إذا كانت نتيجة توقع () أعلى من الوسيطةtoBeGreaterThanOrEqual
صحيح إذا كانت نتيجة توقع () تساوي الوسيطة ، أو أعلى من الوسيطةtoBeLessThan
صحيح إذا كانت نتيجة توقع () أقل من الوسيطةtoBeLessThanOrEqual
صحيح إذا كانت نتيجة توقع () تساوي الوسيطة ، أو أقل من الوسيطةtoMatch
يستخدم لمقارنة السلاسل معتعبير عادينمط مطابقةtoContain
يستخدم في المصفوفات ، صحيح إذا كانت المصفوفة المتوقعة تحتوي على الوسيطة في مجموعة عناصرهاtoHaveLength(number)
: يتحقق من طول المصفوفةtoHaveProperty(key, value)
: يتحقق مما إذا كان الكائن له خاصية ، ويتحقق اختياريًا من قيمتهtoThrow
يتحقق مما إذا كانت الوظيفة التي تمررها تؤدي إلى استثناء (بشكل عام) أو استثناء محددtoBeInstanceOf()
: يتحقق مما إذا كان الكائن هو مثيل لفئة
يمكن إبطال كل تلك المطابقات باستخدام.not.
داخل البيان ، على سبيل المثال:
test('Adding 1 + 1 does not equal 3', () => {
expect(sum(1, 1)).not.toBe(3)
})
للاستخدام مع الوعود ، يمكنك استخدامها.resolves
و.rejects
:
expect(Promise.resolve('lemon')).resolves.toBe('lemon')
expect(Promise.reject(new Error(‘octopus’))).rejects.toThrow(‘octopus’)
يثبت
قبل إجراء اختباراتك ، ستحتاج إلى إجراء بعض التهيئة.
للقيام بشيء ما مرة واحدة قبل تشغيل جميع الاختبارات ، استخدم ملفbeforeAll()
وظيفة:
beforeAll(() => {
//do something
})
لأداء شيء ما قبل تشغيل كل اختبار ، استخدمbeforeEach()
:
beforeEach(() => {
//do something
})
تمزيق
تمامًا كما تفعل مع الإعداد ، يمكنك أيضًا تنفيذ شيء ما بعد كل اختبار:
afterEach(() => {
//do something
})
وبعد انتهاء جميع الاختبارات:
afterAll(() => {
//do something
})
مجموعة الاختبارات باستخدام وصف ()
يمكنك إنشاء مجموعات من الاختبارات ، في ملف واحد ، تعزل وظيفتي الإعداد والتفكيك:
describe('first set', () => {
beforeEach(() => {
//do something
})
afterAll(() => {
//do something
})
test(/*...*/)
test(/*...*/)
})
describe(‘second set’, () => {
beforeEach(() => {
//do something
})
beforeAll(() => {
//do something
})
test(/…/)
test(/…/)
})
اختبار الكود غير المتزامن
يمكن أن تحتوي الشفرة غير المتزامنة في JavaScript الحديثة على شكلين أساسيين: عمليات الاسترجاعات والوعود. علاوة على الوعود ، يمكننا استخدام عدم التزامن / انتظار.
عمليات الاسترجاعات
لا يمكنك إجراء اختبار في رد الاتصال ، لأن Jest لن ينفذه - ينتهي تنفيذ ملف الاختبار قبل استدعاء رد الاتصال. لإصلاح ذلك ، قم بتمرير معلمة إلى وظيفة الاختبار ، والتي يمكنك الاتصال بها بسهولةdone
. ستنتظر Jest حتى تتصلdone()
قبل إنهاء هذا الاختبار:
//uppercase.js
function uppercase(str, callback) {
callback(str.toUpperCase())
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require(’./src/uppercase’)
test(uppercase 'test' to equal 'TEST'
, (done) => {
uppercase(‘test’, (str) => {
expect(str).toBe(‘TEST’)
done()
}
})
وعود
مع وظائف تعود بالوعود ، نحنعودة الوعدمن الاختبار:
//uppercase.js
const uppercase = str => {
return new Promise((resolve, reject) => {
if (!str) {
reject('Empty string')
return
}
resolve(str.toUpperCase())
})
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require(’./uppercase’)
test(uppercase 'test' to equal 'TEST'
, () => {
return uppercase(‘test’).then(str => {
expect(str).toBe(‘TEST’)
})
})
يمكن اختبار الوعود المرفوضة باستخدام.catch()
:
//uppercase.js
const uppercase = str => {
return new Promise((resolve, reject) => {
if (!str) {
reject('Empty string')
return
}
resolve(str.toUpperCase())
})
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require(’./uppercase’)
test(uppercase 'test' to equal 'TEST'
, () => {
return uppercase(’’).catch(e => {
expect(e).toMatch(‘Empty string’)
})
})
غير متزامن / انتظار
لاختبار الدوال التي تعيد الوعود ، يمكننا أيضًا استخدام غير متزامن / انتظار ، مما يجعل بناء الجملة واضحًا وبسيطًا للغاية:
//uppercase.test.js
const uppercase = require('./uppercase')
test(`uppercase 'test' to equal 'TEST'`, async () => {
const str = await uppercase('test')
expect(str).toBe('TEST')
})
السخرية
في الاختبار ،السخريةيسمح لك باختبار الوظائف التي تعتمد على:
- قاعدة البيانات
- شبكة الاتصالالطلبات
- الولوج إلىالملفات
- أيخارجيالنظام
لهذا السبب:
- تجري اختباراتكأسرع، مما يمنح وقتًا استجابة سريعًا أثناء التطوير
- اختباراتكمستقلحالة الشبكة ، أو حالة قاعدة البيانات
- اختباراتك لا تفعل ذلكتلوثأي تخزين للبيانات لأنها لا تلمس قاعدة البيانات
- لا يؤدي أي تغيير يتم إجراؤه في الاختبار إلى تغيير حالة الاختبارات اللاحقة ، ويجب أن تبدأ إعادة تشغيل مجموعة الاختبار من نقطة بداية معروفة وقابلة للتكرار
- لا داعي للقلق بشأن تقييد معدل مكالمات API وطلبات الشبكة
يكون الاستهزاء مفيدًا عندما تريد تجنب الآثار الجانبية (مثل الكتابة إلى قاعدة بيانات) أو إذا كنت تريد تخطي الأجزاء البطيئة من التعليمات البرمجية (مثل الوصول إلى الشبكة) ، كما تتجنب الآثار المترتبة على تشغيل اختباراتك عدة مرات (على سبيل المثال ، تخيل وظيفة ترسل البريد الإلكتروني أو المكالمات API محدودة السعر).
والأهم من ذلك ، إذا كنت تكتب أاختبار الوحدة، يجب أن تختبر وظيفة وظيفة ما بمعزل عن كل ما يمسها من أمتعة.
باستخدام mocks ، يمكنك التحقق مما إذا تم استدعاء وظيفة الوحدة النمطية والمعلمات التي تم استخدامها ، باستخدام:
expect().toHaveBeenCalled()
: تحقق مما إذا تم استدعاء وظيفة التجسسexpect().toHaveBeenCalledTimes()
: احسب عدد مرات استدعاء وظيفة التجسسexpect().toHaveBeenCalledWith()
: تحقق مما إذا كان قد تم استدعاء الوظيفة بمجموعة محددة من المعلماتexpect().toHaveBeenLastCalledWith()
: تحقق من معلمات آخر مرة تم فيها استدعاء الوظيفة
حزم التجسس دون التأثير على كود الوظائف
عند استيراد حزمة ، يمكنك إخبار Jest بـ "التجسس" على تنفيذ وظيفة معينة ، باستخدامspyOn()
، دون التأثير على كيفية عمل هذه الطريقة.
مثال:
const mathjs = require('mathjs')
test(The mathjs log function
, () => {
const spy = jest.spyOn(mathjs, ‘log’)
const result = mathjs.log(10000, 10)
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
اسخر من حزمة كاملة
يوفر Jest طريقة مناسبة للسخرية من حزمة كاملة. إنشاء__mocks__
المجلد في جذر المشروع ، وفي هذا المجلد ، قم بإنشاء ملف JavaScript واحد لكل من الحزم الخاصة بك.
لنفترض أنك تستوردmathjs
. إنشاء__mocks__/mathjs.js
ملف في جذر مشروعك ، وأضف هذا المحتوى:
module.exports = {
log: jest.fn(() => 'test')
}
هذا سوف يسخر من وظيفة السجل () للحزمة. أضف العديد من الوظائف كما تريد للسخرية منها:
const mathjs = require('mathjs')
test(The mathjs log function
, () => {
const result = mathjs.log(10000, 10)
expect(result).toBe(‘test’)
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
استهزأ بوظيفة واحدة
يمكنك السخرية من وظيفة واحدة باستخدامjest.fn()
:
const mathjs = require('mathjs')
mathjs.log = jest.fn(() => ‘test’)
test(The mathjs log function
, () => {
const result = mathjs.log(10000, 10)
expect(result).toBe(‘test’)
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
تستطيع ايضا استخذامjest.fn().mockReturnValue('test')
لإنشاء محاكاة بسيطة لا تفعل شيئًا سوى إرجاع قيمة.
نماذج مسبقة الصنع
يمكنك العثور على نماذج مسبقة الصنع للمكتبات الشعبية. على سبيل المثال هذه الحزمةhttps://github.com/jefflau/jest-fetch-mockيسمح لك بالسخريةfetch()
المكالمات ، وتقديم عينات من قيم الإرجاع دون التفاعل مع الخادم الفعلي في اختباراتك.
اختبار اللقطة
يعد اختبار اللقطات ميزة رائعة جدًا تقدمها Jest. يمكنه حفظ كيفية عرض مكونات واجهة المستخدم الخاصة بك ومقارنتها بالاختبار الحالي ، مما يؤدي إلى حدوث خطأ إذا كان هناك عدم تطابق.
هذا اختبار بسيط على مكون التطبيق لملفcreate-react-app
التطبيق (تأكد من تثبيتreact-test-renderer
):
import React from 'react'
import App from './App'
import renderer from 'react-test-renderer'
it(‘renders correctly’, () => {
const tree = renderer.create(<App />).toJSON()
expect(tree).toMatchSnapshot()
})
في المرة الأولى التي تجري فيها هذا الاختبار ، يحفظ Jest اللقطة في ملف__snapshots__
مجلد. إليك ما يحتويه App.test.js.snap:
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<div
className="App"
>
<header
className="App-header"
>
<img
alt="logo"
className="App-logo"
src="logo.svg"
/>
<h1
className="App-title"
>
Welcome to React
</h1>
</header>
<p
className="App-intro"
>
To get started, edit
<code>
src/App.js
</code>
and save to reload.
</p>
</div>
`
كما ترى أنه الرمز الذي يعرضه مكون التطبيق ، لا شيء أكثر من ذلك.
في المرة التالية التي يقارن فيها الاختبار إخراج<App />
الى هذا. إذا تغير التطبيق ، فستتلقى خطأ:
عند استخدامyarn test
فيcreate-react-app
أنت فيوضع المشاهدة، ومن هناك يمكنك الضغطw
وأظهر المزيد من الخيارات:
Watch Usage
› Press u to update failing snapshots.
› Press p to filter by a filename regex pattern.
› Press t to filter by a test name regex pattern.
› Press q to quit watch mode.
› Press Enter to trigger a test run.If your change is intended, pressing u
will update the failing snapshots, and make the test pass.
You can also update the snapshot by running jest -u
(or jest --updateSnapshot
) outside of watch mode.
More devtools tutorials:
- Introduction to Yeoman
- Bower, the browser package manager
- Introduction to Frontend Testing
- Using node-webkit to create a Desktop App
- VS Code: use language-specific settings
- Introduction to Webpack
- A short and simple guide to Babel
- An introduction to Yarn
- Overview of the Browser DevTools
- Format your code with Prettier
- Keep your code clean with ESLint
- A list of cool Chrome DevTools Tips and Tricks
- Testing JavaScript with Jest
- How to use Visual Studio Code
- Introduction to Electron
- Parcel, a simpler webpack
- An Emmet reference for HTML
- The V8 JavaScript Engine
- Configuring VS Code
- Configuring the macOS command line
- How to disable an ESLint rule
- How to open VS Code from the command line
- How to set up hot reload on Electron