بسم الله الرّحمن الرّحیم
معرفی
یکی از مهمترین کارهایی که در ساخت برنامهی تحت وب باید انجام داد تست کردن آن است. در این راستا میخواهیم با مهمترین مفاهیم، اصطلاحات، ابزارها و رویکردهای تست برنامههای جاوااسکریپتی آشنا شویم.
به صورت کلی برنامهنویسان JavaScript علاقهی زیادی به تست سایتشان ندارند. زیرا نوشتن تست معمولاً سخت، زمانبر و پرهزینه است. ولی با انتخاب استراتژی و ترکیب درستی از ابزارهای موجود میتوان به خوبی تقریباً همهی قسمتهای سایت را منظّم، ساده و نسبتاً سریع تست کرد.
خلاصهی کل این مقاله: برای آزمون واحد و آزمون یکپارچگی از Jest استفاده کنید، و برای آزمون رابط کاربری از TestCafe استفاده کنید
انواع آزمون
به صورت کلی سه نوع آزمون مهم داریم:
- Unit Test (آزمون واحد): تست کردن هر تابع یا کلاس به تنهایی آزمون واحد نامیده میشود. در این آزمون، ورودیهای مورد نظر را به تابع میدهیم و مطمئن میشویم خروجی تابع همان چیزی است که انتظار داریم.
- Integration Test (آزمون یکپارچگی): در آزمون یکپارچگی، فرآیندها و Componentها را تست میکنیم تا مطمئن شویم درست کار میکنند و اثرات جانبی (side effect) آنها را نیز در نظر میگیریم.
- UI Test (آزمون رابط کاربری): در این آزمون که به آزمون functional هم معروف است سناریوهای اصلی محصول خود را تست میکنیم. در این آزمون مرورگر یا سایت را کنترل میکنیم و بدون توجّه به کدهایی که نوشتهایم بررسی میکنیم که آیا محصول ما همان طور که انتظار داریم درست کار می کند یا نه.
انواع ابزارهای آزمون
ابزارهای آزمون براساس عملکرد به چند دسته تقسیم میشوند:
- آزمون را در مرورگر یا Node اجرا و راه اندازی میکنند.
- ساختار آزمون را تعیین میکند. (Mocha, Jasmine, Jest, Cucumber)
- توابع assertion را تعیین میکند. (Chai, Jasmine, Jest, Unexpected)
- نتایج آزمون را تولیدکرده، نمایش میدهد و زیر نظر میگیرد. (Mocha, Jasmine, Jest, Karma)
- از وضعیت فعلی برنامه و مؤلفهها و ساختمان دادهها snapshot میگیرد تا مطمئن شود نسبت به قبل چیزی خراب نشده باشد. (Jest, Ava)
- دادههای mock تولید میکند. (Sinon, Jasmine, enzyme, Jest, testdouble)
- میزان پوشش کد را گزارش میدهد. (Istanbul, Jest, Blanket)
- محیطی مشابه مرورگر، یا حتّی مرورگر واقعی فراهم میکند و اجرای سناریوی مورد نظر را کنترل میکند. (Protractor, Nightwatch, Phantom, Casper)
- بررسی میکنند که رابط کاربری برنامه از نظر ظاهری نسبت به قبل تغییری نکرده باشد.
ساختار آزمون که جهت سازماندهی آزمونها به کار میرود امروزه بیشتر به صورت BDD استفاده میشود، و معمولاً به این شکل است:
describe('calculator', function() {
// ماژولها را با استفاده از توابع describe توصیف میکنیم
describe('add', function() {
// رفتار مورد انتظار را مشخّص میکنیم
it('should add 2 numbers', function() {
// در اینجا برای تست رفتار مورد انتظار از توابع assertion استفاده میکنیم
...
})
})
})
توابع assersion تابعهایی هستند که از آنها برای اطمینان از اینکه مقدار یک متغیّر همان چیزی است که ما انتظار داریم، به کار میروند. این توابع معمولاً به شکلهای زیر نوشته میشوند (دو مورد اوّل مشهورتر است):
// Chai کتابخانه
expect(foo).to.be.a('string')
expect(foo).to.equal('bar')
// Jasmine کتابخانه
expect(foo).toBeString()
expect(foo).toEqual('bar')
// Chai کتابخانه
assert.typeOf(foo, 'string')
assert.equal(foo, 'bar')
// Unexpected کتابخانه
expect(foo, 'to be a', 'string')
expect(foo, 'to be', 'bar')
Spy اطلاعاتی در مورد تابع میدهد، از قبیل اینکه چندبار فراخوانی شدهاست، در چه مواردی، و توسط چه کسی؟
در آزمون یکپارچگی برای اطمینان از اینکه اثرات جانبی (Side Effect) همان طور که انتظار داریم است از Spy استفاده میکنیم. برای مثال میخواهیم ببینیم در حین یک فرآیند چندبار فلان تابعِ ماشینحساب فراخوانی شده است؟
it('should call method once with the argument 3', () => {
// ایجاد یک spy با کتابخانه sinon برای object.method
const spy = sinon.spy(object, 'method')
// فراخوانی متد با آرگومان ورودی «۳»
object.method(3)
// مطمئن میشویم object.method فقط یکبار فراخوانی شده باشد و آرگومان ورودی درست باشد
assert(spy.withArgs(3).calledOnce)
})
Stubbing یا dubbing تابع انتخاب شده را با تابعی دیگر جایگزین میکند تا مطمئن شویم ماژول مورد نظر رفتار مورد انتظار ما را دارد.
مثلاً اگر بخواهیم خیالمان راحت باشد که تابع user.isValid()
در حین تست یک مؤلفهی خاص همیشه مقدار true بر میگرداند، میتوانیم این طوری بنویسیم:
// Sinon کتابخانه
sinon.stub(user, 'isValid').returns(true)
// stubها در کتابخانه Jasmine در واقع همان spyها هستند که قابلیت اضافهتری دارند
spyOn(user, 'isValid').andReturns(true)
Mock یا Fake رفتار یا ماژولهای خاصی را جعل میکند، تا بتواند قسمتهای مختلف پروسه را تست کند.
مثلاً کتابخانهی Sinon میتواند یک سرور تقلّبی جعل کند، تا در حین تست یک فرآیند حالتهایی مثل آفلاین بودن، سریع بودن سرور و… را مورد آزمایش قرار دهید.
it('returns an object containing all users', done => {
// ایجاد و پیکربندی سرور تقلبی
const server = sinon.createFakeServer()
server.respondWith('GET', '/users', [
۲۰۰,
{ 'Content-Type': 'application/json' },
'[{ "id": 1, "name": "Gwen" }, { "id": 2, "name": "John" }]'
])
// فراخوانی فرآیندی که شامل یک درخواست از طریق شبکه است که تقلید میشود
Users.all()
.done(collection => {
const expectedCollection = [
{ id: 1, name: 'Gwen' },
{ id: 2, name: 'John' }
]
expect(collection.toJSON()).to.eql(expectedCollection)
done()
})
// پاسخ به درخواست
server.respond()
// حذف سرور تقلبی
server.restore()
})
آزمون Snapshot در مواقعی به کار میرود که بخواهید یک ساختمانداده را با چیزی که انتظار دارید مقایسه کنید.
مثال زیر که در مستندات Jest است نمونهای از آزمون Snapshot را برای یک Link نشان میدهد:
it('renders correctly', () => {
// یک نمونه از کامپوننت Link میسازیم
const linkInstance = (
Facebook
)
// ایجاد یک Snapshot از کامپوننت
const tree = renderer.create(linkInstance).toJSON()
// مقایسه با آخرین Snapshot موجود
expect(tree).toMatchSnapshot()
})
در این مثال واقعاً از روی این مؤلفه عکس گرفته نشده است که مقایسهاش کنیم، ولی همهی اطّلاعات داخلی این مؤلفه درون یک فایل مجزّا به این صورت ذخیره شده است:
exports[`renders correctly 1`] = `
<a
className="normal"
href="//www.facebook.com"
onMouseEnter={[Function]}
onMouseLeave={[Function]}
>
Facebook
</a>
`;
وقتی تست اجرا شود و Snapshot با چیزی که ذخیره شده است متفاوت باشد، کاربر متوجّه میشود که این مؤلفه تغییر کرده است. مثلاً در Jest چنین چیزی را میبیند:
هرچند که آزمون Snapshot برای تست Componentها استفاده میشود، ولی هر نوع دادهی دیگری را نیز میتواند مقایسه کند، از جمله redux storeها و ساختار داخلی قسمتهای مختلف برنامه.
انواع محیطهای مرورگر یا مرورگرمانند
- jsdom – محیطی با جاوااسکریپت خالص که مرورگر را شبیهسازی میکند و اصلاً UI ندارد.
- مرورگر Headless – مرورگری که بدون UI اجرا میشود تا سریعتر تست را اجرا کند.
- مرورگر واقعی – مرورگری واقعی که تست را اجرا میکند.
همه چیز با هم
توصیهی ما این است که ابزاری پیدا کنید که (۱) ساختار آزمون را مشخص کند، (۲) دارای توابع assertion باشد، (۳) نتایج را گزارش دهد و زیر نظر بگیرد.
توصیهی بعدی ما این است که فرآیند UI testing را از unit testing و integration testing جدا کنید. زیرا اجرای تستهای UI زمان بیشتری میطلبد، مخصوصاً اگر بخواهید روی چند مرورگر مختلف این تستها را انجام دهید.
آزمون واحد (Unit)
در این آزمون به تک تک تابعها ورودیهای ساده و همچنین ورودیهای لبمرزی بدهید و بعد با کمک توابع assertion (۲) مطمئن شوید خروجی آنها همان چیزی است که انتظار دارید. همچنین از یک ابزار برای گزارش میزان پوشش کد (۶) استفاده کنید تا بدانید تستهای شما چه مقدار از کلّ کدهایی که نوشتهاید را پوشش دادهاند.
هرچه توابع نوشته شده pure باشند آزمون واحد سادهتر میشود. تابع pure به تابعی میگویند که خروجی آن غیر از پارامترهای ورودیاش به چیز دیگری وابسته نباشد.
آزمون یکپارچگی (Integration)
این آزمون میتواند خرابیهایی را شناسایی کند که اصلاح یک قسمت از کد موجب خرابی یک جای دیگر شده است.
در دنیای واقعی همهی Unitها pure نیستند و همهی آنها قابل آزمون نیستند. بنابراین unitها باید به عنوان بخشی از یک فرآیند بزرگتر مورد آزمون قرار بگیرند.
در Integration testing باید فرآیندهای بین ماژولهای مختلف پوشش داده شوند، و ممکن است نیاز داشته باشید از spyها استفاده کنید تا بتوانید اثرات جانبی را تست کنید. گاهی اوقات لازم است از stubها استفاده کنید تا بخشی از یک فرآیند را که به آزمون ما مرتبط نیست تغییر دهید یا تقلید کنید.
در این آزمونها یک محیط مرورگر یا مرورگرمانند (۷) میتواند برای اجرای فرآیندهایی که به شیء window در مرورگر وابسته هستند، یا فرآیندهایی که بخشی از آنها رندر کردن یک Component یا تعامل با یک Component است کمک کند.
تستهای Snapshot (۴) نیز در این دستهبندی قرار میگیرند. با این طور تستها میتوانیم ببینیم فرآیند مورد نظر چه بلایی بر سر کامپوننتهای انتخاب شده میآورد، بدون اینکه لازم باشد از یک محیط مرورگر یا مرورگرمانند استفاده کرد.
آزمون رابط کاربری (UI)
این آزمونها همواره به محیط مرورگر یا مرورگرمانند (۷) نیاز دارند.
این آزمون رفتار کاربر نهایی با مرورگر را شبیهسازی میکند (کارهایی مثل کلیک کردن، تایپ کردن، اسکرول کردن و…) تا مطمئن شویم سناریوهای برنامه از نظر کاربر نهایی به درستی کار میکند.
راه اندازی این نوع تستها از بقیه سختتر است. یک لحظه فکر کنید خودتان میخواهید سایتتان را روی دستگاههای مختلف و مرورگرهای مختلف و نسخههای مختلف آنها تست کنید. از این رو سرویسهای زیادی ساختهشدهاند که این کار را برایتان انجام دهند.
ابزارهای عمومی
jsdom
یک پیادهسازی جاوااسکریپتی از استانداردهای Web است. محیط یک مرورگر را فقط با اجرای کد سادهی جاوااسکریپت شبیهسازی میکند. این ابزار پیشرفت خیلی سریعی داشتهاست و نسخهی فعلی آن خیلی به یک مرورگر واقعی نزدیک است.
مزایا: اجرای آزمونها به صورت خیلی سریع
معایب: همهچیز را نمیتوان شبیهسازی کرد (مثلا نمیتوان screenshot گرفت).
Istanbul
ابزاری است که مقدار پوشش کد در آزمون واحد را گزارش میدهد. میتواند مقدار پوشش دستورات، پوشش خط، و پوشش توابع را گزارش دهد. از این رو خواهید دانست کدام قسمت از کدهایتان را تست نکردهاید و باید تست کنید.
Karma
ابزاری برای اجرای آزمونها در محیط مرورگر یا مرورگرمانند است.
Karma یک سرور آزمون میسازد که صفحهی وب خاصی را میزبانی میکند. و آزمونها را در محیط آن صفحه اجرا میکند. این صفحهی وب میتواند در مرورگرهای مختلف باز شود. حتّی میتوان با کمک سرویسهایی مثل BrowserStack از راه دور آزمونها را اجرا کرد.
Chai
مشهورترین کتابخانهی assertion است.
Unexpected
کتابخانهای برای assertion است که syntax متفاوتی از Chai دارد. ساختاری گسترشپذیر دارد و کتابخانههایی مثل unexpected-react با assertionهای خاص برپایهی آن ساخته شده اند.
Sinon.JS
spy، stub و mock ایجاد میکند، و با هر فریمورک آزمون واحدی میتواند کار کند.
testdouble.js
کتابخانهای مثل Sinon است، و ادعا دارد که بهتر از آن عمل میکند. تفاوتهای کوچکی نیز از نظر طرّاحی و طرز تفکّر و بعضی خصوصیات با Sinon دارد.
Wallaby
ابزاری غیر رایگان است که روی IDE نصب میشود (همهی IDEهای مشهور را پشتیبانی میکند) و متناسب با تغییرات کد، کد شما را تحلیل میکند و در همان لحظه در کنار کدتان خرابیها را نشان میدهد.
Cucumber
کمک میکند تا در قالب BDD آزمون بنویسید. آزمون را به دو بخش معیار پذیرش (که در فایلی مجزا نوشته میشود و syntax آن Gherkin است) و نیز فایل آزمون متناسب با آن تقسیم میکند.
چارچوبهای آزمون واحد و یکپارچگی
به صورت خلاصه اگر میخواهید فقط شروع به کار کنید و دنبال چارچوبی سریع برای پروژههای بزرگ هستید از Jest استفاده کنید.
اگر پیکربندی انعطافپذیر و توسعهپذیر میخواهید از Mocha استفاده کنید.
اگر دنبال سادگی بیشتر هستید از Ava استفاده کنید.
اگر میخواهید low-level کار کنید از tape استفاده کنید.
Mocha
پراستفادهترین کتابخانهی تست در جاوااسکریپت است. برای assertion، mocking و spying از ابزارهای دیگر (third-party) استفاده میکند (معمولاً Enzyme و Chai). بنابراین راهاندازی آن نسبت به چارچوبهای دیگر سختتر است، ولی انعطاف بیشتری دارد. و افزونههای زیادی برایش ساخته شده است. توابع مربوط به ساختار آزمون را به صورت global تعریف میکند (که البته شامل assertionها و… نمیشود).
Jest
چارچوب آزمون مورد توصیهی FaceBook است. بر پایهی Jasmine ساختهشدهاست. رابط کاربری ساده و راحتی دارد.
کارایی: با پیادهسازی روشی هوشمندانه به صورت موازی سرعت را مخصوصا برای پروژههای بزرگتر بسیار افزایش داده است. ضمناً در حالت Watch (حالتی که فایلها را زیر نظر میگیرد و با هر تغییر در فایل، تستها را اجرا میکند) فقط تستهای مربوط به همان قسمت تغییریافته را دوباره اجرا میکند و بنابراین در این حالت سرعت خیلی خوبی دارد.
آمادهی استفاده: از ابتدا در خودش امکاناتی برای assertion، spy، mock دارد. البته اگر نمیخواهید، میتوانید از کتابخانههای دلخواه خود هم استفاده کنید.
Snapshot: کتابخانهی jest-snapshot برای این کار توسّط FaceBook توسعه و نگهداری میشود.
پوشش کد: ابزاری برای پوشش کد دارد که بر اساس Istanbul ساخته شده است.
توابع مهم برای آزمون را به صورت global تعریف میکند.
Jasmine
چارچوبی است که Jest بر پایهی آن ساخته شده است.
آمادهی استفاده: هرچیزی که برای آزمون لازم است را دارد.
جامعه: مقالات و ابزارهای بسیاری برمبنای آن به وجود آمدهاند.
Angular: پشتیبانی گستردهای از تمام نسخههای Angular دارد، و چارچوب آزمون مورد توصیه در مستندات Angular است.
توابع مهم برای آزمون را به صورت global تعریف میکند.
Ava
کتابخانهای حداقلی (minimalistic) برای اجرای آزمونها به صورت موازی است.
آمادهی استفاده: هرچیزی که برای آزمون لازم است را در خودش دارد، و با Node.js اجرا میشود.
سادگی: برای ساختار و assertionها API سادهای دارد و در عین حال دارای ویژگیهایی حرفهایست.
کارایی: آزمونها را در پروسههای جدای Node.js اجرا میکند. سرعت زیادی در حالت Watch دارد، زیرا فقط آزمونهای مربوط به همان قسمت تغییریافته را دوباره اجرا میکند.
Snapshot: به عنوان بخشی از این framework پیادهسازی شدهاست.
هیچ تابع یا متغیّری را به صورت global تعریف نمیکند.
tape
یک فایل js ساده است که توسّط Node.js اجرا میشود و API کوتاه و بهدردبخوری دارد.
سادگی: ساختار حداقلی و assertion بدون API پیچیده، حتّی سادهتر از Ava.
هیچ تابع یا متغیّری را به صورت global تعریف نمیکند.
حالت اشتراکی بین آزمونها وجود ندارد، یعنی نباید مثل چارچوبهای دیگر از توابعی مثل beforeEach استفاده کرد تا قبل از اجرای هرکدام از آزمونها دستوراتش اجرا شود.
نیازی به CLI ندارد. فقط با کمک یک فایل js ساده اجرا میشود.
ابزارهای آزمون رابط کاربری
سرویسهایی هستند که میتوانند اینگونه آزمونهای شما را در مرورگرها و دستگاههای مختلف به صورت خودکار برایتان اجرا کنند (مثل BrowserStack).
ابزارهای این دسته تفاوتهای خیلی زیادی دارند، از پیادهسازی گرفته، تا طرز نگاه و تفکر پشت آن، و API مورد استفاده.
به صورت خلاصه اگر فقط میخواهید شروع به کار کنید، و ابزاری قابل اطمینان و سریع میخواهید که به صورت cross-browser کار کند و همهی چیزهای لازم را همراه خود داشته باشد از TestCafe استفاده کنید.
اگر میخواهید ابزاری را استفاده کنید که اکثر افراد از آن استفاده میکنند و Community Support خوبی داشته باشید از WebdriverIO استفاده کنید.
اگر پشتیبانی Cross-browser برایتان مهم نیست از Puppeteer استفاده کنید.
اگر برنامهی شما رابط کاربری و گرافیک پیچیدهای ندارد، از ابزارهای cross-browser و headless مثل Casper استفاده کنید.
Selenium
مرورگر را خودکار میکند. در اصل فقط برای اهداف آزمون نوشته نشدهاست. یک سرور میسازد که از طریق یک API رفتار کاربر را در مرورگر شبیهسازی میکند.
راههای زیادی برای کنترل آن وجود دارد، از زبانهای برنامهنویسی مختلف پشتیبانی میکند، و ابزارهایی حتّی بدون برنامهنویسی برای کار با آن ساختهشدهاند.
برای نیازهای ما، سرور Selenium توسّط Selenium WebDriver کنترل میشود که به صورت یک لایهی ارتباطی بین NodeJS و سرور Selenium عمل میکند.
Node.js <=> WebDriver <=> Selenium Server <=> FF/Chrome/IE/Safari
میتوانید WebDriver را در چارچوب آزمون خود import کنید و آزمونهای خود را برپایهی آن بنویسید.
خود WebDriver را میتوان مستقیماً استفاده کرد، ولی با این حال کتابخانههای مختلفی نیز آن را گسترش دادهاند که در ادامه بررسی میکنیم.
Appium
ابزاریست که API مشابه Selenium دارد، و هدف آن آزمون برنامههای کاربردی تحت وب در گوشیهای موبایل است، که برای هر سیستم عامل از ابزاری متفاوت استفاده میکند (از iOS و Android و Windows Phone پشتیبانی میکند).
بنابراین اگر از Selenium یا ابزارهای مبتنی بر آن استفاده کنید، میتوانید برای آزمون آن بر روی گوشیهای موبایل از Appium هم استفاده کنید.
Protractor
ابزاری مبتنی بر Selenium است که syntax بهبودیافته و ویژگیهایی خاص برای آزمون برنامههای مبتنی بر چارچوب Angular دارد. در مستندات Angular استفاده از این ابزار توصیه شده است. فرآیند خوبی برای گزارش خطاها دارد. از TypeScript هم پشتیبانی میکند و توسّط خود تیم توسعهی Angular تولید و نگهداری میشود.
WebdriverIO
یک پیادهسازی از Selenium WebDriver است. Syntax ساده و خوانایی دارد. انعطافپذیر و توسعهپذیر است. جامعهی وسیعی دارد و افزونههای زیادی برایش ساختهشده است.
Nightwatch
یک پیادهسازی از Selenium WebDriver است. چارچوب آزمون مربوط به خودش را دارد، همراه با سرور آزمون، assertionها و… البته میتوان آن را با frameworkهای دیگر نیز به کار برد. Syntax خیلی ساده و خوانایی دارد. به نظر میرسد پشتیبانی ضعیفتری نسبت به دیگران داشته باشد.
TestCafe
جایگزین خوبی برای ابزارهای مبتنی بر Selenium است. در سال ۲۰۱۶ متنباز شدهاست. ولی همچنان یک نسخهی پولی به صورت جداگانه دارد با این تفاوت که نسخهی پولی شامل ابزارهایی بدون نیاز به برنامهنویسی است.
راهاندازی آن سریع است. Cross-browser و cross-device است (با سرویسهایی مثل BrowserStack سازگار است و میتواند آزمونها را در مرورگرهای Headless نیز اجرا کند). میتواند آزمونها را به صورت موازی روی چند مرورگر به طور همزمان اجرا کند، که به طور چشمگیری سرعت آزمون را افزایش میدهد. گزارشگیری خطاها راحت است. ساختار آزمون مربوط به خودش را دارد که کار را سادهتر میکند ولی ممکن است افرادی از آن خوششان نیاید.
Cypress
رقیب TestCafe و شبیه به آن است. مثل آن آزمونها را به صفحهی وب تزریق میکند، ولی به صورت انعطافپذیرتر و راحتتر.
در حال حاضر فقط مرورگر Chrome را پشتیبانی میکند. قابلیتهای خیلی حرفهای ندارد (مثل اجرای آزمونها به صورت موازی). مستندات سرراست و تمیزی دارد. فرآیند خطایابی و logging خوبی دارد. برای ساختار آزمون از Mocha استفاده میکند که باعث میشود نسبتاً استاندارد باشد و آزمون UI هم در ساختار مشابه آزمون واحد نوشته شود.
Puppeteer
کتابخانهای برای Node.js است که توسّط گوگل توسعه داده شدهاست. و یک API ساده برای کنترل Headless Chrome ارائه می دهد.
وقتی مرورگر Chrome 59+ را با فلگ –headless اجرا کنید، Headless Chrome را اجرا کردهاید.
بد نیست اشاره کنیم مرورگر Firefox هم از اواخر سال ۲۰۱۷ نسخهی Headless خود را ارائه داده است.
Puppeteer نسبتاً جدید است، ولی در عین حال جامعهی بزرگی دارد که از آن استفاده میکنند و ابزارهایی مبتنی بر آن توسعه میدهند.
به خاطر native بودن و استفاده از موتور آخرین نسخهی مرورگر Chrome سریع است، برعکس PhantomJS که مبتنی بر نسخهی قدیمیتری از WebKit ساخته شده است.
یکی از نقصهای Puppeteer در حال حاضر عدم پشتیبانی از افزونههای Chrome (مثل flash) میباشد.
PhantomJS
یک پیادهسازی از موتور مرورگر Chromium است و هدف آن ایجاد یک مرورگر headless قابل کنترل بود. بعد از انتشار Puppeteer توسّط گوگل، سازنده و توسعهدهندگان PhantomJS کار روی آن را رها کردند.
با وجود Puppeteer چرا PhantomJS به عنوان یک گزینه مطرح شد؟ زیرا PhantomJS چارچوبی بالغ است. ابزارهای زیادی مثل CasperJS مبتنی بر آن هستند. از آنجایی که از نسخهی قدیمی WebKit استفاده میکند میتواند برای شبیهسازی مرورگرهای قدیمی به کار برود. ضمناً Phantom از افزونههایی مثل Flash پشتیبانی میکند (برخلاف Puppeteer).
Nightmare
کتابخانهای عالی برای آزمون UI است که syntax خیلی سادهای دارد.
Nightmare از Electron استفاده میکند که شبیه Phantom است، ولی از نسخهی جدید Chromium استفاده میکند و توسعهی آن همچنان با قدرت ادامه دارد، به خاطر اینکه هدف Electron ساخت برنامههای کاربردی تحت Desktop و cross-platform با HTML و CSS و JavaScript است.
Casper
Casper مبتنی بر PhantomJS و SlimerJS است (SlimerJS چیزی شبیه Phantom برای موتور Gecko در Firefox است) و کارهایی مثل navigation، اسکریپتنویسی و testing-utilities را به صورت انتزاعی به دور از پیچیدگیهای کدهای async در Phantom و Slimer انجام میدهد.
Slimer در اواخر سال ۲۰۱۷ نسخهی beta خود را ارائه داد و در آن از Headless firefox استفاده کرد و در حال حاضر هنوز نسخهی release نهایی خود را منتشر نکرده است.
Casper در نسخهی ۲ از Phantom به Puppeteer مهاجرت خواهد کرد.
CodeceptJS
مثل CucumberJS که قبلاً بحث کردیم طرز تفکری متفاوت از بقیهی ابزارها دارد، و API آن نیز بسیار متفاوت است و روی رفتار کاربر تمرکز میکند. کدهایی که با syntax خاص Codecept نوشته میشوند توسّط WebdriverIO، Protractor، Nightmare، Appium یا Puppeteer اجرا میشود.