سرو-پیکربندی آسان چند منظوره

این که آیا اجرای زیر مجموعه ای از آزمایشات در برابر یک محیط محلی ، یک مجموعه رگرسیون در برابر یک محیط میزبان ، UAT یا هر چیز دیگری که در آن وجود دارد ، آزمایش در برابر محیط های مختلف یک عمل مهم و معمول در طول چرخه زندگی توسعه است.
در این مقاله یک الگوی آسان ، تمیز و مقیاس پذیر برای اجرای هر محیطی با سرو نشان می دهم.
قبل از غواصی در اجرای ، بیایید برخی از راه حل های جایگزین را کشف کنیم ، چرا محدود هستند و مزایای آنها را تا زمانی که بهینه ترین راه حل را تعریف نکنیم ، ایجاد کنیم.
راه حل های جایگزین:
به صورت دستی cypress.config.js را به روز کنیدبشر
کمترین بهینه ترین رویکرد به روزرسانی دستی است cypress.config.js
هر بار که یک محیط متفاوت مورد نیاز است.
با نگاهی به یک فایل پیکربندی ساده در زیر ، برای یک محیط محلی ، کاربر نیاز به تغییر دارد baseUrl
و هر دو متغیر خاص ENV فقط در صورت تمایل به اجرای مجدد محلی ، باید آنها را تغییر دهند. با افزایش این پرونده و تنظیمات و متغیرهای بیشتر در محیط ها متفاوت است ، به روز کردن دستی این پرونده هر بار نه تنها مالیات بلکه غیر عملی است.
const { defineConfig } = require('cypress')
require('dotenv').config({ path: '../.env' })
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
return require('./cypress/plugins/index')(on, config)
},
baseUrl: 'http://127.0.0.1:8009/',
},
env: {
MY_USER: process.env.MY_LOCAL_USER,
MY_PASSWORD: process.env.MY_LOCAL_PASSWORD,
},
})
جوانب مثبت:
- سریع برای یک راه حل یک بار
منفی ها:
- ادغام تغییرات بر همه تأثیر می گذارد
- تکراری و وقت گیر
- اجرای CI/CD را محدود می کند
گزینه های خط فرمانبشر
رویکرد دیگر استفاده از CLI با غلبه بر هرگونه تنظیمات پیش فرض یا متغیرها با پارامترها است. این راه حل به کاربران امکان می دهد چندین فرمان اجرا را تعریف کنند ، هرکدام با غلبه خاصی برای آن محیط.
در مثال زیر ، دو دستور اسکریپت در package.json
پرونده از آنجا که cypress.config.js
پرونده برای محیط محلی پیکربندی شده است. cy:run
فرمان نیازی به اصلاح هر چیزی ندارد. با این حال ، cy:run:dev
فرمان هر دو را تحت الشعاع قرار می دهد baseUrl
و متغیرهای محیطی با استفاده از --config
وت --env
گزینه ها
"cy:run": "cypress run",
"cy:run:dev": "cypress run --config baseUrl=https://myDevURL, --env MY_USER=some-dev-user,MY_PASSWORD=some-dev-password"
این به کاربران امکان می دهد با تغییر فرمان که اجرا می کنند ، به سادگی تغییر کنند که در مقابل کدام محیطی را اجرا می کنند. این نه تنها سریعتر از رویکرد قبلی بلکه دستی کمتر است. انجام این کار در صورت وجود اختلافات اندک بین محیط ها بهینه است ، بنابراین دستورات اجرا کوچک باقی می مانند. برای محیط هایی که دارای اختلافات بیشتری هستند ، عبور در پارامترهای متعدد می تواند با رشد انحرافات خسته کننده و سخت باشد.
علاوه بر این ، توصیه نمی شود رازهای موجود در package.json
بنابراین این رویکرد آنچه را که متغیرهای محیطی می توانند نادیده بگیرند محدود می کند.
جوانب مثبت:
- برای تفاوت های کوچک محیطی مفید است
- از سوئیچینگ سریع محیط پشتیبانی کنید
- کتابچه راهنمای کاربر کمتر
منفی ها:
- با افزایش تفاوت های محیطی مقیاس نمی یابد
- مجبور به نادیده گرفتن اسرار در یک پرونده عمومی
شرط آزمایش
در حالی که هر دو راه حل فوق برای اختلافات کوچک محیطی کار می کنند ، در مورد محیط هایی که بین آنها تفاوت زیادی دارند ، چه می شود؟
یک راه برای رسیدگی package.json
دستورات و در عوض در یک محیط واحد عبور می کنند ، متغیر مانند ENVIRONMENT
"cy:run": "cypress run",
"cy:run:dev": "cypress run --env ENVIRONMENT=development",
"cy:run:qa": "cypress run --env ENVIRONMENT=qa",
"cy:run:uat": "cypress run --env ENVIRONMENT=uat",
اکنون منطق مشروط را می توان در مجموعه تست با انجام اجرا کرد Cypress.env('ENVIRONMENT')
برای دسترسی به متغیر بیایید نگاهی به یک آزمایش اساسی در تلاش برای ورود به سیستم و تجزیه آن بیندازیم.
const getUrl = () => {
switch (Cypress.env('ENVIRONMENT')) {
case 'local':
return 'http://127.0.0.1:8009/'
case 'development':
return 'my-dev-url/'
case 'qa':
return 'my-qa-url/'
case 'uat':
return 'my-uat-url/'
default:
break
}
}
const setEnvVariables = () => {
switch (Cypress.env.ENVIRONMENT) {
case 'local':
Cypress.env('MY_USER', 'some user')
Cypress.env('MY_PASSWORD', 'some password')
case 'development':
Cypress.env('MY_USER', 'some dev user')
Cypress.env('MY_PASSWORD', 'some dev password')
case 'qa':
Cypress.env('MY_USER', 'some qa user')
Cypress.env('MY_PASSWORD', 'some qa password')
case 'uat':
Cypress.env('MY_USER', 'some uat user')
Cypress.env('MY_PASSWORD', 'some uat password')
default:
break
}
}
describe('My Test Suite', () => {
beforeEach(() => {
setEnvVariables()
})
it('Basic Test', () => {
// Visit
cy.visit(getUrl())
// Login
cy.get('login-user-input').type(Cypress.env('MY_USER'))
cy.get('login-password-input').type(Cypress.env('MY_PASSWORD'))
})
})
با استفاده از منطق مشروط سوئیچ/مورد ، ما قادر به بررسی گذرگاه هستیم ENVIRONMENT
گزینه و داده های URL صحیح و احراز هویت را در خود آزمون تنظیم کنید.
در حالی که این رویکرد CLI را پاک می کند و تمام منطق را در مجاورت بقیه کد آزمون حرکت می دهد ، یک تن منطق تکراری لازم برای تحقق این امر وجود دارد و هرچه مقادیر خاص env خاص رشد می کنند ، تکرار فقط بدتر می شود. حتی اگر این یاران انتزاعی شوند ، هر آزمایش نیاز به ایجاد این منطق و در نتیجه کمیت کد بسیار بیشتر از سایر گزینه های دیگر دارد. سرانجام ، این مسئله با همان مسئله ای روبرو است که اسرار علنی آن تعریف شده است.
جوانب مثبت:
- CLI را ساده می کند
- اطلاعات خاص محیط را نزدیک به کد آزمون حرکت می دهد
منفی ها:
- منطق مشروط کپی
- مقدار بیشتری از کد مورد نیاز برای دستیابی به همان راه حل
- سردرگمی بالقوه داشتن داده های پیکربندی در هر دو پرونده پیکربندی و در مجموعه تست.
- مجبور به تعریف اسرار در یک پرونده عمومی
راه حل بهینه
اکنون که چندین راه حل جایگزین مورد بررسی قرار گرفته است ، بیایید به راه حلی بپردازیم که تمام جوانب مثبت را از راه حل های جایگزین ترکیب کند به گونه ای که از اضافه کردن یک محیط جدید فوق العاده آسان پشتیبانی می کند.
اینگونه کار می کند
- در
cypress.config.js
پرونده برای هر دو تنظیمات جهانی در همه محیط ها و همچنین تنظیمات فردی برای بیشترین استفاده از محیط (مانند محلی) تعریف شده است. - در
dotenv
از کتابخانه برای وارد کردن اسرار از محلی استفاده می شود.env
پرونده این اسرار با استفاده ازprocess.env.X
نحو
const { defineConfig } = require('cypress')
require('dotenv').config({ path: '../.env' })
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
return require('./cypress/plugins/index')(on, config)
},
baseUrl: 'http://127.0.0.1:8009/',
},
env: {
MY_USER: process.env.MY_LOCAL_USERNAME,
MY_PASSWORD: process.env.MY_LOCAL_PASSWORD,
},
})
-
بعد ، اضافی
cypress.config.X.js
ایجاد شده اند ، یکی برای هر محیط. این پرونده های پیکربندی فقط آنچه برای آن محیط متفاوت است را تعریف کنید، در حالی که تنظیمات باقیمانده با پخش از پایه به ارث می برندcypress.config.js
پرونده -
بنابراین در مثال زیر ، پایه
cypress.config.js
پرونده وارد می شود ، QAbaseUrl
و متغیرهای ورود به سیستم ناپدید می شوند و پیکربندی کلی با گسترش همه چیز به هم تعریف می شود.
const { defineConfig } = require('cypress')
const baseConfig = require('./cypress.config')
const e2eOverride = {
baseUrl: 'https://my-qa-url.com/',
}
const envOverride = {
MY_USER: process.env.MY_QA_USERNAME,
MY_PASSWORD: process.env.MY_QA_PASSWORD,
}
module.exports = defineConfig({
...baseConfig,
e2e: {
...baseConfig.e2e,
...e2eOverride,
},
env: {
...baseConfig.env,
...envOverride,
},
})
- سرانجام ، هر محیط دستور اجرای خود را دارد که در یک گزینه CLI واحد عبور می کند
config-file
- توجه کنید که
cy:run
دستور در یک پرونده پیکربندی عبور نمی کند ، به معنای پیش فرضcypress.config.js
استفاده خواهد شد
"cy:run": "cypress run",
"cy:run:dev": "cypress run --config-file cypress.config.dev.js",
"cy:run:qa": "cypress run --config-file cypress.config.qa.js",
"cy:run:uat": "cypress run --config-file cypress.config.uat.js",
و همین است.
دویدن در برابر QA به سادگی اجرای آن است cy:run:qa
یا cy:run:uat
برای یک uat env در حالی که پایه است cy:run
فرمان از آزمایش محلی پشتیبانی می کند. من همچنین توصیه می کنم env خاص ایجاد کنید cy:open
دستورات استفاده از دونده آزمون در کنار دستورات RUN برای استفاده از CI ، CI/CD.
این الگوی نه تنها تمیز است بلکه اضافه کردن یک محیط جدید به آسانی ایجاد یک دستور جدید و فایل پیکربندی خاص ENV است. علاوه بر این ، اشکال زدایی یا اصلاح هر تنظیمات ساده است ، زیرا تغییرات سطح جهانی به راحتی در پرونده پیکربندی پایه پیچیده می شوند در حالی که تمام تغییرات خاص ENV به طور جداگانه اتفاق می افتد. وارد کردن اسرار مهم از .env
پرونده ها نیز امکان پذیر است.
امیدوارم که این امر به پیکربندی محیطی شما کمک کند و به جلو حرکت کند. از خواندن شما متشکرم
آزمایش مبارک!