Detox یک فریمورک برای تست gray-box E2E برنامههای موبایل است که توسط تیم Wix به طور خاص برای پروژههای React Native ساخته شده است. برخلاف رویکردهای black-box، Detox به وضعیت داخلی برنامه دسترسی دارد که امکان همگامسازی خودکار بدون تایماوت دستی را فراهم میکند. بر اساس دادههای Wix Engineering, 2026، همگامسازی خودکار زمان اجرای تست را در مقایسه با مکثهای سنتی ۴۰٪ کاهش میدهد.
نکات کلیدی
Detox یک فریمورک برای تست جامع (E2E) برنامههای موبایل است که توسط شرکت Wix در سال ۲۰۱۷ توسعه یافته است. این فریمورک برای پروژههای React Native طراحی شده، اما از برنامههای کاملاً بومی در iOS و Android نیز پشتیبانی میکند. Detox با مدل gray-box کار میکند، به این معنی که به مکانیسمهای داخلی برنامه دسترسی دارد.
تفاوت اصلی Detox با Appium یا Calabash همگامسازی خودکار با برنامه است. فریمورک قبل از انجام اقدام بعدی منتظر پایان انیمیشنها، درخواستهای شبکه و پردازش رویدادها میماند. این کار نیاز به Thread.sleep() یا waitForElement را که تستها را کند میکنند، کاملاً از بین میبرد.
Detox از iOS (از طریق XCTest و Xcode) و Android (از طریق Espresso و UI Automator) پشتیبانی میکند. برای برنامههای React Native پشتیبانی کامل از Fabric و معماری قدیمی فراهم شده است. در iOS تستها روی شبیهساز و در Android روی شبیهساز یا دستگاه واقعی اجرا میشوند.
معماری Detox از سه مؤلفه کلیدی تشکیل شده است: Detox CLI، اجراکننده تست Detox و درایور بومی Detox. Detox CLI ساخت برنامه، نصب و اجرای تستها را مدیریت میکند. اجراکننده تست (Jest یا Mocha) سناریوهای تست را اجرا کرده و از طریق WebSocket با برنامه ارتباط برقرار میکند.
تست gray-box به این معنی است که Detox از طریق پل بومی به وضعیت داخلی برنامه دسترسی دارد. فریمورک درخواستهای شبکه، انیمیشنها، تایمرها و صف عملیات را ردیابی میکند. وقتی همه صفها خالی هستند — Detox برنامه را برای مرحله بعدی آماده میداند.
همگامسازی بر پایه ردیابی رشته اصلی (main thread) برنامه است. Detox منتظر میماند تا همه انیمیشنها پایان یابند، درخواستهای HTTP پاسخ برگردانند و مدیریتکنندههای رویداد اجرا شوند. اگر تست به دلیل انیمیشن بینهایت هنگ کند — میتوان همگامسازی را برای یک بلوک کد خاص به اجبار غیرفعال کرد.
// غیرفعالسازی همگامسازی برای بخش مشکلدار
await device.disableSynchronization();
// اقدام با انیمیشن طولانی
await element(by.id('loader')).swipe('down');
await device.enableSynchronization();
نصب Detox با افزودن بسته از طریق npm یا yarn شروع میشود. پس از نصب باید یک فایل پیکربندی .detoxrc.js ایجاد شود که تنظیمات ساخت و اجرا را برای هر پلتفرم توصیف میکند. Detox از نوع ساخت مخصوص خود برای iOS استفاده میکند که بر اساس پیکربندی Xcode است.
پیکربندی شامل مسیر برنامه (app)، نوع سازنده (build)، آرگومانهای ساخت و تنظیمات دستگاه (device) است. برای iOS از appleSimulator و برای Android از androidEmulator استفاده میشود. همچنین میتوان آرگومانهای راهاندازی مانند زبان یا منطقه شبیهساز را مشخص کرد.
// .detoxrc.js — نمونه پیکربندی
module.exports = {
testRunner: { args: { '$0': 'jest', config: 'e2e/config.json' } },
apps: {
'ios.debug': { type: 'ios.app', build: 'xcodebuild ...' },
'android.debug': { type: 'android.apk', build: 'cd android && ./gradlew ...' }
},
devices: {
simulator: { type: 'ios.simulator', device: { type: 'iPhone 15' } },
emulator: { type: 'android.emulator', device: { avdName: 'Pixel_4_API_34' } }
}
};
پس از پیکربندی، دستورات زیر در دسترس هستند: detox build — ساخت برنامه با پرچمهای تست و detox test — اجرای تستها. Detox از اجرای همزمان روی چندین دستگاه با پرچم --workers پشتیبانی میکند.
تستهای Detox با JavaScript یا TypeScript با استفاده از API مبتنی بر جستجوی عناصر (matchers) و اقدامات (actions) نوشته میشوند. Matchers امکان یافتن عنصر را با شناسه، متن، نوع یا موقعیت روی صفحه فراهم میکنند. Actions کلیک، وارد کردن متن، کشیدن و اسکرول را انجام میدهند.
یک تست معمولی به صورت دنبالهای است: عنصر را پیدا کن → عمل را انجام بده → نتیجه را بررسی کن. برای بررسی از expect-API با matchers بر اساس وجود، دید یا متن عنصر استفاده میشود. Detox از سینتکس describe/it از طریق ادغام با Jest پشتیبانی میکند.
describe('Login flow', () => {
beforeEach(async () => {
await device.reloadReactNative();
});
it('should log in with valid credentials', async () => {
await element(by.id('emailInput')).typeText('user@test.com');
await element(by.id('passwordInput')).typeText('password123');
await element(by.id('loginButton')).tap();
await expect(element(by.id('homeScreen'))).toBeVisible();
});
});
Detox از همه ژستهای محبوب پشتیبانی میکند: tap، longPress، swipe، scroll، pinch، multiTap. برای scroll میتوان جهت، سرعت و موقعیت توقف را مشخص کرد. این امکان تست سناریوهای پیچیده مانند pull-to-refresh یا carousel را فراهم میکند.
Detox به خوبی با سیستمهای CI محبوب ادغام میشود: GitHub Actions، CircleCI، Bitrise و Jenkins. برای اجرا در CI نیاز به پیکربندی شبیهساز مجازی iOS (بدون GUI) و شبیهساز Android با شتاب سختافزاری است. Detox مصنوعات — اسکرینشات و لاگ — را برای تحلیل تستهای ناموفق ارائه میدهد.
برای تسریع اجرای تستها در CI توصیه میشود از sharding (موازیسازی) با پرچم --workers استفاده کنید. Detox به طور خودکار فایلهای تست را بین چندین شبیهساز توزیع میکند. همچنین ذخیرهسازی buildهای برنامه بین اجراها برای کاهش زمان ساخت مفید است.
# GitHub Actions — اجرای Detox در iOS
- name: Install Dependencies
run: npm ci
- name: Build Detox App
run: npx detox build --configuration ios.sim
- name: Run Detox Tests
run: npx detox test --configuration ios.sim --workers 2
timeout-minutes: 30
برای تستهای E2E پایدار و سریع توصیه میشود چند قانون را رعایت کنید. از sleep() خودداری کنید — Detox همگامسازی خودکار را فراهم میکند و تأخیرهای صریح فقط تستها را کند و ناپایدار میکنند. اگر تست به دلیل زمانبندی ناموفق است، ابتدا بررسی کنید که همگامسازی غیرفعال نشده باشد. همچنین گروهبندی تستها بر اساس ویژگی و اجرای مستقل آنها مفید است — این کار یافتن علت شکست را ساده میکند.
Detox چندین متد device برای مدیریت وضعیت ارائه میدهد: device.reloadReactNative() باندل را بارگذاری مجدد میکند، device.launchNewApp() برنامه را با پارامترهای جدید راهاندازی میکند، device.sendToHome() برنامه را کوچک میکند. device.setURLBlacklist() امکان حذف URLهای خاص از همگامسازی را فراهم میکند که برای آنالیتیکس و اتصالات long-polling مفید است.
برای هر تست توصیه میشود وضعیت ایزوله ایجاد کنید. از beforeEach برای بارگذاری مجدد برنامه از طریق device.reloadReactNative() استفاده کنید. برای تستهایی که به دادههای خاص نیاز دارند، کارخانهها یا کلاینتهای API برای آمادهسازی داده در سرور ایجاد کنید. از وابستگی بین تستها خودداری کنید — هر تست باید مستقل باشد.
Detox تست WebView را از طریق متدهای web.element() و web.invoke() پشتیبانی میکند. برای تعامل با عناصر وب از by.web(id، css یا className) استفاده میشود. مهم است به خاطر داشته باشید که WebView به زمان اضافی برای بارگذاری نیاز دارد — اگر همگامسازی کار نمیکند، انتظار بارگذاری را از طریق waitFor اضافه کنید.
// تست WebView در Detox
const webView = web(by.id('webview'));
await webView.element(by.web.cssSelector('#submit-btn')).tap();
const result = await webView.element(
by.web.cssSelector('.result-text')
).getText();
await expect(result).toEqual('Success');
Detox مقایسه اسکرینشات را از طریق پلاگین detox-image-matching پشتیبانی میکند. اسکرینشاتها امکان شناسایی رگرسیونهای بصری را فراهم میکنند: عناصر جابجا شده، رنگهای نادرست، آیکونهای گمشده. برای اسکرینشاتهای پایدار، انیمیشنها را غیرفعال کنید و از اندازه ثابت شبیهساز استفاده کنید.
رایجترین مشکلات Detox مربوط به همگامسازی است: انیمیشنهای بینهایت، درخواستهای طولانی شبکه یا تایمرهای معلق. لاگگیری با پرچم --loglevel trace نشان میدهد که Detox منتظر چه منابعی است. اگر Detox هنگ کرد — از device.disableSynchronization() برای بخش کد مشکلدار استفاده کنید.
در شبیهساز iOS، Detox نیاز به ساخت قبلی برنامه از طریق xcodebuild با پیکربندی iphonesimulator دارد. خطای رایج — استفاده از طرح Release به جای Debug که پرچمهای تست را غیرفعال میکند. برای Android مطمئن شوید AVD با API سازگار با برنامه شما ایجاد شده و شتاب Intel HAXM فعال است. برای محیطهای CI در macOS استفاده از GitHub Actions با رانر macOS راحت است، جایی که Xcode و شبیهسازها از قبل نصب شدهاند.
اگر تستها به طور مرتب به دلیل تایماوت ناموفق میشوند، بررسی کنید: آیا همگامسازی به صورت سراسری غیرفعال نشده، آیا در کد برنامه از setTimeout یا setInterval بدون پاکسازی استفاده نشده، و آیا عملیات طولانی رشته اصلی را مسدود نمیکند. گاهی افزایش تایماوت در detoxrc.js از طریق testRunner.args.jest.$.testTimeout کمک میکند. برای یافتن بخشهای مشکلدار، لاگگیری ردیابی Detox را فعال کنید — نشان میدهد که فریمورک در حال حاضر منتظر چه منابع و تایمرهایی است.
پس از اجرای تستها، Detox مصنوعات ایجاد میکند: اسکرینشات تستهای ناموفق، لاگ برنامه و گزارشهای XML JUnit. اسکرینشاتها به طور خودکار در صورت ناموفق بودن تست گرفته میشوند و به شناسایی بصری مشکل کمک میکنند. برای CI مصنوعات به فضای ذخیرهسازی ابری بارگذاری میشوند و از طریق رابط وب برای تحلیل علل شکست در دسترس هستند.
سؤالات متداول
Detox از رویکرد gray-box با دسترسی به وضعیت داخلی برنامه و همگامسازی خودکار استفاده میکند. Appium با مدل black-box از طریق WebDriver کار میکند و نیاز به انتظارهای دستی دارد. Detox برای پروژههای React Native سریعتر و پایدارتر است.
تستهای Detox با JavaScript یا TypeScript نوشته میشوند. فریمورک با Jest و Mocha به عنوان اجراکننده تست ادغام میشود. موتور بومی برای iOS به Swift و برای Android به Kotlin و Java نوشته شده است.
بله، Detox از برنامههای بومی در iOS (از طریق XCTest) و Android (از طریق Espresso) پشتیبانی میکند. با این حال مخاطب اصلی Detox توسعهدهندگان React Native هستند، زیرا برای پروژههای بومی راهحلهای بالغتری وجود دارد.
Detox مصنوعات ارائه میدهد: اسکرینشات، لاگ برنامه و گزارشهای HTML. برای دیباگ محلی از پرچم --loglevel trace و برای CI از جمعآورنده خودکار مصنوعات با بارگذاری در ابر استفاده میشود.
این یک متد Detox API است که باندل JavaScript برنامه React Native را بدون نصب مجدد بارگذاری مجدد میکند. در beforeEach برای بازنشانی وضعیت برنامه به صفحه اولیه قبل از هر تست استفاده میشود.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید