रूबी/रेल डेवलपर्स के रूप में, हम परीक्षण लिखना पसंद करते हैं। परीक्षण सॉफ्टवेयर विकास का एक अभिन्न अंग है। अच्छे परीक्षण हमें उच्च-गुणवत्ता वाला कोड लिखने में मदद करते हैं। वे समग्र विकास प्रक्रिया में मूल्य जोड़ते हैं, लेकिन अगर हम परीक्षण को अच्छी तरह से प्रबंधित नहीं करते हैं, तो वे हमें धीमा कर सकते हैं। गलत तरीके से प्रबंधित किए जाने वाले परीक्षणों के कुछ लक्षण यहां दिए गए हैं:
- परीक्षण चलाने में लंबा समय लगता है।
- परीक्षण अविश्वसनीय हैं और बेतरतीब ढंग से विफल हो जाते हैं।
- विभिन्न मशीनों पर परीक्षण अलग तरह से व्यवहार करते हैं।
- सभी परीक्षण सूट चलाने से आपका CI धीमा हो जाता है।
इस ब्लॉग पोस्ट में, हम कवर करेंगे कि परीक्षण को विश्वसनीय बनाने के लिए कंटेनरों का उपयोग कैसे किया जा सकता है, जो उच्च गुणवत्ता वाले सॉफ़्टवेयर को वितरित करने में सहायक है।
एकीकरण परीक्षण और इकाई परीक्षण
इससे पहले कि हम कंटेनरों के विषय में कूदें, आइए पहले इकाई और एकीकरण परीक्षणों के बीच के अंतर को समझें और एक ही पृष्ठ पर हों।
यूनिट परीक्षण अलगाव में कोड के एक ब्लॉक का परीक्षण करने का एक तरीका है। वे कोड के ब्लॉक की कार्यक्षमता का परीक्षण करने में मदद करते हैं लेकिन निर्भरता नहीं। उदाहरण के लिए, यहाँ एक आसान तरीका है:
def sum(a, b)
a + b
end
यह एक ऐसा फलन है जो दो संख्याओं का योग करता है, जो बहुत सरल है। इस फ़ंक्शन का परीक्षण करना बहुत आसान होगा। लेकिन क्या होगा अगर इस फ़ंक्शन की बाहरी सेवा पर निर्भरता है। एक बार योग पूरा करने के बाद इस विधि को डेटाबेस को लिखना होता है।
def sum!(a, b)
c = a + b
Sum.create(value: c)
end
कोड के इस ब्लॉक में, मान जोड़े जाते हैं और डेटाबेस में सहेजे जाते हैं। कोड के इस ब्लॉक का परीक्षण करने के लिए, हमें एक डेटाबेस सर्वर चलाना होगा। यदि हम डेटाबेस सर्वर के साथ इसका परीक्षण करते हैं, तो यह अब एक इकाई परीक्षण नहीं है। इसके लिए बाहरी निर्भरता की आवश्यकता होती है, और हम डेटाबेस कनेक्शन का परीक्षण भी करेंगे और क्या डेटाबेस में रिकॉर्ड सहेजा गया है। इस मामले में, यह परीक्षण एक एकीकरण परीक्षण है।
यूनिट परीक्षण एकल इकाई परीक्षण . हो सकते हैं (सभी निर्भरताओं का मजाक/स्टब) या मिलनसार इकाई परीक्षण (अन्य निर्भरताओं से बात करने की अनुमति दें)। लोगों ने इकाई परीक्षणों की विभिन्न परिभाषाएँ प्रस्तावित की हैं। इस ब्लॉग के संदर्भ में, हम जिस प्रकार की इकाई परीक्षण की बात कर रहे हैं, वह एकान्त इकाई परीक्षण है।
मॉक के साथ बाहरी निर्भरता को हटाने से परीक्षण तेजी से चलने में मदद मिलती है। यूनिट परीक्षणों का उपयोग करते समय, हम इन निर्भरताओं को छोड़ देते हैं, लेकिन यह सुनिश्चित करने के लिए कि एप्लिकेशन अपेक्षित रूप से काम करता है, निर्भरताओं का परीक्षण भी उतना ही महत्वपूर्ण है। डेटाबेस, नेटवर्क कॉल और फ़ाइलों जैसे इन बाहरी निर्भरताओं का परीक्षण करने के लिए हम जो परीक्षण लिखते हैं, वे एकीकरण परीक्षण हैं ।
इकाई परीक्षणों की तरह, लोगों ने एकीकरण परीक्षणों की विभिन्न परिभाषाएँ प्रस्तावित की हैं। हालाँकि, मूल अवधारणा समान है। अंतर केवल दायरे में है। डेटाबेस को लिखने वाला एक छोटा कार्य एकीकरण परीक्षण हो सकता है। एक व्यापक कार्यक्षमता जो सिस्टम के कई हिस्सों को जोड़ती है वह भी एक एकीकरण परीक्षण है। हम यहां जिस परीक्षण के बारे में बात कर रहे हैं वह संकीर्ण भाग पर अधिक केंद्रित है। परीक्षण जितना छोटा होगा, हमें उतने ही अधिक परीक्षण लिखने होंगे। हालांकि, व्यापक परीक्षणों के साथ, आवश्यक परीक्षणों की संख्या कम हो जाती है।
एकीकरण परीक्षण चलाते समय, हमें एप्लिकेशन और निर्भरता, जैसे डेटाबेस और बाहरी सेवाओं को चलाने की आवश्यकता होती है। इन निर्भरताओं को प्रबंधित करना चुनौतीपूर्ण हो सकता है।
डॉकर के बुनियादी सिद्धांत
डॉकर एक ऐसी तकनीक है जो किसी एप्लिकेशन को उसके पर्यावरण (ऑपरेटिंग सिस्टम) से अमूर्त करने में मदद करती है और इसे होस्ट के साथ अलगाव में चलाती है। यह एक वर्चुअल मशीन के समान है लेकिन तेज और अधिक कुशल है। डॉकर हमें अपने एप्लिकेशन कोड और उसकी निर्भरता को एक कंटेनर में पैकेज करने की अनुमति देता है। यह कोड को पोर्टेबल बनाने में मदद करता है और इसका मतलब है कि हमारे पास विकास, परीक्षण और उत्पादन के दौरान एक ही डॉकर छवि चल सकती है। यह उस वातावरण की स्थिरता सुनिश्चित करेगा जिसमें एप्लिकेशन चलता है। चूंकि यह होस्ट सर्वर पर निर्भर नहीं है, इसलिए यह सभी वातावरणों में एप्लिकेशन के व्यवहार को अनुमानित बनाता है। डॉकर डेवलपर्स को एप्लिकेशन और उसके वातावरण को चलाने और प्रबंधित करने में मदद करता है, जिसमें सरल कमांड का उपयोग करके निर्माण, चलाना, परिनियोजन और अद्यतन करना शामिल है।
आइए कुछ महत्वपूर्ण शब्दावली को समझते हैं:
-
डॉकरफ़ाइल - डॉकरफाइल केवल एक फाइल है जहां हम एप्लिकेशन के लिए आवश्यक निर्भरता को परिभाषित करते हैं। हम उस ऑपरेटिंग सिस्टम को निर्दिष्ट कर सकते हैं जिसकी उसे आवश्यकता है, डेटाबेस क्लाइंट लाइब्रेरी, या एप्लिकेशन द्वारा आवश्यक कोई भी पैकेज। यहां, हम एप्लिकेशन को चलाने के लिए आवश्यक कमांड को भी परिभाषित करते हैं। Dockerfile मूल छवि से प्रारंभ होता है। ये आधार छवियां एक ऑपरेटिंग सिस्टम या प्रोग्रामिंग भाषा हो सकती हैं।
-
छवियां - छवियां एक खाका है जो एक कंटेनर को चलाने के लिए आवश्यक चरणों को बताता है। छवियों को विभिन्न परतों के साथ बनाया गया है। Dockerfile में परिभाषित प्रत्येक चरण छवि के भीतर एक परत है। यह पुन:प्रयोज्यता बढ़ाता है और छवि को तेजी से बनाने के लिए मध्यवर्ती परत को कैशिंग करने में मदद करता है।
-
कंटेनर - कंटेनर वास्तविक चित्र हैं। ये रुकी हुई अवस्था में भी हो सकते हैं। कंटेनर को डॉक इमेज से शुरू किया जा सकता है। एक एकल डॉकटर छवि कई डॉकटर कंटेनर शुरू कर सकती है। कंटेनर छवि द्वारा निर्दिष्ट जानकारी रखते हैं। एक पतली कंटेनर परत होती है जहां एप्लिकेशन के चलने के दौरान छवि में किए गए सभी परिवर्तन संग्रहीत होते हैं।
-
डॉकर लिखें - डॉकर कंपोज़ एक अलग टूल है जो कई कंटेनरों को प्रबंधित करने में मदद करता है। हमारे पास एक ही डॉकटर छवि से कई कंटेनर हो सकते हैं। हमें विभिन्न डॉकटर छवियों से कई कंटेनरों की भी आवश्यकता हो सकती है, और इन कंटेनरों को एक दूसरे के साथ बातचीत करने की आवश्यकता होती है। डॉकर कंपोज़ कंटेनरों का प्रबंधन करता है। अन्य उपकरण उपलब्ध हैं, लेकिन इस संदर्भ में, हम इसकी सादगी के कारण केवल Docker Compose का उपयोग करेंगे।
वर्चुअल मशीनें होस्ट हाइपरवाइजर के शीर्ष पर होती हैं और उन्हें एक अलग ऑपरेटिंग सिस्टम स्थापित करने की आवश्यकता होती है, इसलिए अधिक होस्ट संसाधनों का उपयोग किया जाता है। हालाँकि, डॉकर के साथ, हमें केवल होस्ट ऑपरेटिंग सिस्टम में डॉकर इंजन स्थापित करने की आवश्यकता होती है, और होस्ट संसाधन प्रबंधन डॉकर द्वारा किया जाता है। Docker डेवलपर्स और sysops दोनों के लिए जीवन को आसान बनाने में मदद करता है, इसलिए यह DevOps संस्कृति में बहुत लोकप्रिय है।
क्यों परीक्षण के लिए Docker का उपयोग करें
डॉकर न्यूनतम संसाधन खपत के साथ अपने मेजबान वातावरण से चल रहे एप्लिकेशन या परीक्षण को अलग करता है। परीक्षण के लिए डॉकर का उपयोग करने के कुछ लाभ यहां दिए गए हैं:
-
हल्के वजन: डॉकर कंटेनर हल्के होते हैं। यह एक ही समय में कई कंटेनरों को चलाने में मदद करता है और एक परीक्षण प्रक्रिया के बिना किसी अन्य परीक्षण प्रक्रिया में कोई समस्या उत्पन्न होती है।
-
पोर्टेबल: डॉकर छवियां पोर्टेबल हैं और किसी भी वातावरण में चल सकती हैं। यह सीआई में मदद करता है, क्योंकि हम स्थानीय और सीआई वातावरण में परीक्षण चलाने के लिए उसी छवि का पुन:उपयोग कर सकते हैं।
-
संस्करण: एकाधिक अनुप्रयोगों का उपयोग करने या हमारी निर्भरता को अपग्रेड करने के लिए हमारी स्थानीय मशीन में हमारी निर्भरता के विभिन्न संस्करणों की आवश्यकता होती है। डॉकर के बिना प्रबंधन करना बहुत मुश्किल होगा। डॉकर के साथ, हमारे पास अलग-अलग संस्करण के साथ चलने वाले अलग-अलग कंटेनर हो सकते हैं। हम विभिन्न संस्करणों पर परीक्षण भी चला सकते हैं और चीजों को सत्यापित कर सकते हैं।
-
माइक्रोसर्विसेज का आसान प्रबंधन :माइक्रोसर्विसेज के साथ, परीक्षण भी वितरित और जटिल हो जाता है। इसका मतलब है कि हमें आश्रित माइक्रोसर्विस को प्रबंधित करने की आवश्यकता है। Docker और Docker Compose इन सेवा निर्भरताओं को प्रबंधित करने में मदद करते हैं।
पूर्व-आवश्यकताएं
इसे आज़माने के लिए, आइए सुनिश्चित करें कि निम्नलिखित सेट अप हैं:
- डॉकर
- डॉकर-लिखें
- रूबी 2.7 (वैकल्पिक, क्योंकि हम रूबी को डॉकर कंटेनर में जोड़ देंगे, लेकिन यह परीक्षण के लिए सहायक होगा)
- रेल (5.1+ अनुशंसित)
ऐप्लिकेशन को डॉकराइज़ करें
आइए एक साधारण रेल ऐप बनाकर और इसे कंटेनरीकृत करके शुरू करें। मैं एक ताजा रेल ऐप से शुरू कर रहा हूं। आप मौजूदा रेल ऐप को कंटेनरीकृत भी कर सकते हैं।
rails new calculator
Dockerfile
. नाम की एक फाइल बनाएं निम्नलिखित सामग्री के साथ:
FROM ruby:2.7
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -y nodejs yarn
RUN mkdir /calculator
WORKDIR /calculator
COPY Gemfile /calculator/Gemfile
COPY Gemfile.lock /calculator/Gemfile.lock
RUN bundle install
COPY package.json /calculator/package.json
COPY yarn.lock /calculator/yarn.lock
RUN yarn install --check-files
COPY . /calculator
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
हमारे द्वारा परिभाषित डॉकरफाइल में रूबी 2.7 बेस इमेज है। हमें NodeJS और यार्न की आवश्यकता है, इसलिए अगला कदम उन्हें स्थापित करना है। एक बार जब वे स्थापित हो जाते हैं, तो हम bundle install
चलाते हैं और yarn install
. अंत में, हम सभी कोड की प्रतिलिपि बनाते हैं और निर्यात किए गए 3000 पोर्ट के साथ रेल सर्वर चलाते हैं। यह एक बहुत ही सरल Dockerfile है। इसके साथ, हमारे रेल ऐप को डॉकटराइज़ किया गया है।
अब हम यह सुनिश्चित करने के लिए डॉकर छवि बना और चला सकते हैं कि यह चल रही है।
डॉकर इमेज बनाएं:
docker build . -t calculator
कंटेनर चलाएँ:
docker run -p 3000:3000 calculator
गणना तर्क के साथ एक मॉडल बनाएं
आइए हम गणना नामक एक मॉडल बनाते हैं जहां हम अपना गणना तर्क जोड़ सकते हैं। हम उनके लिए कुछ तर्क और परीक्षण लिखने के लिए इस मॉडल का उपयोग करेंगे। हम देख सकते हैं कि डॉकर कंपोज़ का उपयोग करके हम इन परीक्षणों की निर्भरता को कैसे प्रबंधित कर सकते हैं।
हम वर्तमान में SQLite के साथ रेल चला रहे हैं। आइए इसे SQLite के बजाय Postgres में बदलें। यह निम्न आदेश के साथ आसानी से किया जा सकता है:
rails db:system:change --to=postgresql
एक गणना मॉडल उत्पन्न करें:
bundle exec rails generate model calculation
गणना स्कीमा में कुछ फ़ील्ड जोड़ें:
# db/migrate/create_calculation.rb
class CreateCalculations < ActiveRecord::Migration[6.0]
def change
create_table :calculations do |t|
t.integer :x
t.integer :y
t.integer :result
t.timestamps
end
end
end
इसके बाद, आइए डेटाबेस को कंटेनर के अंदर माइग्रेशन चलाने का प्रयास करें:
docker-compose exec web rails db:migrate
चूंकि डेटाबेस कंटेनर के अंदर नहीं चल रहा है, इसलिए इस कमांड को चलाने से एक त्रुटि होगी।
rake aborted!
PG::ConnectionBad: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
हम एक पोस्टग्रेज छवि को दूसरी छवि के रूप में चला सकते हैं और उनके बीच एक नेटवर्क जोड़ सकते हैं। इस कंटेनर संचार को प्रबंधित करने के लिए, हम Docker Compose का उपयोग कर सकते हैं।
एकाधिक कंटेनरों को प्रबंधित करने के लिए Docker Compose का उपयोग करना
रेल ऐप कंटेनरीकृत होने के साथ, हम डॉकटर कंपोज़ का उपयोग करके सेवा में निर्भरताएँ जोड़ सकते हैं। आवेदन पर निर्भरता Postgres है।
Postgres Docker छवि सार्वजनिक रूप से उपलब्ध है, इसलिए हमें इसे बनाने की आवश्यकता नहीं है। हालांकि, हमें डेटाबेस कंटेनर और हमारे रेल ऐप कंटेनर को प्रबंधित करने की आवश्यकता है।
version: "3.0"
services:
db:
image: postgres
environment:
POSTGRES_USER: calculator
POSTGRES_PASSWORD: password
POSTGRES_DB: calculator_test
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
environment:
CALCULATOR_DATABASE_PASSWORD: password
अब, database.yaml
. पर जाएं फ़ाइल और डेटाबेस को किसी भिन्न होस्ट में बदलें। होस्ट डॉकर कंपोज़ फ़ाइल में सेवा के अंदर निर्दिष्ट नाम होगा। हमारे मामले में, होस्ट db
है . सुनिश्चित करें कि postgres
. में DB पासवर्ड समान है सेवा और web
सर्विस। साथ ही, डॉकर कंपोज़ फ़ाइल में निर्दिष्ट उपयोगकर्ता नाम, पासवर्ड और डेटाबेस का नाम बदलें।
# database.yaml
development:
<<: *default
database: calculator_development
username: calculator
password: <%= ENV['CALCULATOR_DATABASE_PASSWORD'] %>
अब, हम एक ही कमांड का उपयोग करके कंटेनर शुरू कर सकते हैं:
docker-compose up
यह डेटाबेस और हमारे रेल सर्वर दोनों को शुरू करेगा। हम अब माइग्रेशन कमांड चला सकते हैं, और यह पोस्टग्रेज से कनेक्ट होने और माइग्रेशन को चलाने में सक्षम होना चाहिए।
टेस्ट जोड़ना
अब जब हमारे पास सभी सेटअप तैयार हैं, तो आइए मॉडल के अंदर एक सरल विधि लिखें और विधि का परीक्षण करें:
# calculation.rb
class Calculation < ApplicationRecord
def self.sum(x, y)
result = x + y
Calculation.create(x: x, y: y, result: result)
result
end
end
यह योग विधि न केवल संख्या जोड़ती है बल्कि संख्या को डेटाबेस में भी सहेजती है। इसलिए, इस पद्धति का परीक्षण करने के लिए डेटाबेस इंस्टेंस को चलाने की आवश्यकता होती है।
यह परीक्षण एक एकीकरण परीक्षण होगा, क्योंकि हमें एक डेटाबेस से जुड़ना होगा।
हम परीक्षण लिखने के लिए मिनी-टेस्ट का उपयोग करेंगे, जो कि रेल डिफ़ॉल्ट है।
# calculation_test.rb
require 'test_helper'
class CalculationTest < ActiveSupport::TestCase
test "should sum and save the data" do
result = Calculation.sum(1, 2)
c = Calculation.last
assert result, 3
assert c.result, result
end
end
परीक्षण चलाएँ:
docker-compose exec web rails test
उपरोक्त परीक्षण में, हम परीक्षण कर रहे हैं कि क्या योग विधि मानों को जोड़ रही है और डेटाबेस में मानों को सहेज रही है। Docker Compose के साथ, हमारे पास डेटाबेस से जुड़ने का एक बहुत ही आसान तरीका है।
यहां, विधि डेटाबेस पर निर्भर है। निर्भरता न केवल एक डेटाबेस बल्कि एक तृतीय-पक्ष सेवा भी हो सकती है जो एक REST API प्रदान करती है। तो, आइए हम एक तृतीय-पक्ष सेवा का उपयोग करने का प्रयास करें जो sum
. प्रदान करती है विधि, जिसे हम स्वयं लिखने के बजाय उपयोग कर सकते हैं।
# calculation.rb
class Calculation < ApplicationRecord
def self.sum(x, y)
# The hostname should be the same as it is specified in the docker-compose file
url = 'https://sumservice:4010/sum'
uri = URI(url)
params = { :x => x, :y => y }
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
throw "Error" unless res.is_a?(Net::HTTPSuccess)
result = res.body.to_i
Calculation.create(x: x, y: y, result: result)
result
end
end
हम आरईएसटी एपीआई के लिए कुछ ऐसा ही कर सकते हैं जो हमने डेटाबेस के लिए निर्भरता के रूप में किया था। हमें यह सुनिश्चित करने की आवश्यकता है कि ये मान्य समापन बिंदु हैं, लेकिन हम परीक्षण के दौरान वास्तविक सेवा पर कॉल नहीं करना चाहते हैं। इस मामले के लिए, हम नकली/आधार परीक्षण बना सकते हैं, लेकिन अगर हम ऐसा करते हैं तो ये परीक्षण एकीकरण परीक्षण नहीं होंगे। हम यह सुनिश्चित करना चाहते हैं कि परीक्षण यथासंभव यथार्थवादी हो। इस उद्देश्य के लिए, हम एक नकली एपीआई एंडपॉइंट बना सकते हैं, जिसे हम एक कंटेनर में चलाएंगे, और नकली कंटेनर एपीआई सेवा को कॉल करेंगे, जो हमें परिणाम के साथ जवाब देगा।
आइए पहले परीक्षण को संशोधित करें:
# calculation_test.rb
require 'test_helper'
class CalculationTest < ActiveSupport::TestCase
test "should sum and save the data" do
result = Calculation.sum(1, 2)
c = Calculation.last
# we don't need this assetion as we are deligation this responsibility to external service:
# assert result, 3 // Not needed
assert c.result, result
end
end
यहां, हमने परीक्षण मामले को केवल यह जांचने के लिए संशोधित किया है कि योग एपीआई द्वारा प्रदान किया गया परिणाम डेटाबेस में ठीक से सहेजा गया है या नहीं। हमें यह जांचने की ज़रूरत नहीं है कि राशि का वास्तविक मूल्य सही है, क्योंकि यह बाहरी सेवा द्वारा नियंत्रित किया जाता है, और हम उन पर भरोसा करते हैं।
मॉक सर्वर बनाने के लिए, हम ओपनएपीआई का उपयोग करेंगे। आइए एक सरल स्वैगर परिभाषा बनाएं:
रूट डायरेक्टरी में एक नया फोल्डर बनाएं और उसे नाम दें mock
. फोल्डर के अंदर एक फाइल नाम बनाएं api.yaml
# api.yaml
swagger: "2.0"
info:
description: "This is a sum api provider"
version: "1.0.0"
title: "API Provider"
host: "https://mock-service.com/"
basePath: "/api"
schemes:
- "https"
- "http"
paths:
/sum:
get:
produces:
- "application/json"
parameters:
- name: "x"
in: "query"
description: "x value"
required: true
type: "integer"
- name: "y"
in: "query"
description: "y value"
required: true
type: "integer"
responses:
"200":
description: "successful operation"
schema:
type: "integer"
example: 3
विनिर्देश के आधार पर इस सर्वर को चलाने के लिए, हम किसी भी नकली सेवा प्रदाता का उपयोग कर सकते हैं। मैं प्रिज्म नामक उपकरण का उपयोग करूंगा। इसमें एक डॉकर इमेज उपलब्ध है, जिसे हम अपनी डॉकर-कंपोज़ फ़ाइल में जोड़ सकते हैं:
version: "3.0"
services:
db:
image: postgres
environment:
POSTGRES_USER: calculator
POSTGRES_PASSWORD: password
POSTGRES_DB: calculator_test
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
- sumservice
environment:
CALCULATOR_DATABASE_PASSWORD: password
sumservice:
image: stoplight/prism:4
command: mock -h 0.0.0.0 "/tmp/api.yaml"
volumes:
- ./mock:/tmp/
ports:
- 4010:4010
init: true
अब, परीक्षण चलाते हैं और देखते हैं कि यह अपेक्षा के अनुरूप काम कर रहा है या नहीं:
> docker-compose exec web rails test
Finished in 0.337710s, 2.9611 runs/s, 5.9222 assertions/s.
1 runs, 2 assertions, 0 failures, 0 errors, 0 skips
हाँ! अब हमारे पास परीक्षण चल रहा है। योग प्राप्त करने के लिए विधि योग सेवा डॉकर छवि से जुड़ती है और डेटा को बचाने के लिए पोस्टग्रेज से जुड़ती है। सभी निर्भरताएँ डॉकर कंपोज़ द्वारा प्रबंधित की जाती हैं, इसलिए हमें पहले से स्थापित निर्भरता के बारे में चिंता करने की आवश्यकता नहीं है। इस परीक्षण को किसी भी मशीन पर ले जाना बिना किसी निर्भरता स्थापना के काम करेगा। केवल एक चीज जो मशीन को चाहिए वह है डॉकटर।
यदि आपका एप्लिकेशन किसी अन्य निर्भरता पर निर्भर करता है, जैसे कि Redis या Memcached, तो ये dockerhub में पाए जा सकते हैं। हम इन छवियों को आवश्यकतानुसार अपनी डॉकर कंपोज़ फ़ाइल में जोड़ सकते हैं।
समानांतर परीक्षण
रेल 5.1.5+ समानांतर में चल रहे परीक्षणों का समर्थन करता है। डिफ़ॉल्ट रूप से, परीक्षण प्रोसेसर की संख्या के आधार पर रेल 6 से समानांतर में चलते हैं। परीक्षण चलाते समय, यह समानांतर परीक्षणों की संख्या के आधार पर डेटाबेस इंस्टेंस बनाता है। यदि हमारे पास चार प्रोसेसर हैं, तो यह डेटाबेस "कैलकुलेटर_टेस्ट-0", कैलकुलेटर_टेस्ट-1, कैलकुलेटर_टेस्ट-2 और कैलकुलेटर_टेस्ट-3 बनाता है। यदि आप पोस्टग्रेज क्ली पर जाते हैं और डेटाबेस की जांच करते हैं, तो आप निम्नलिखित देखेंगे:
> \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-------------------+------------+----------+------------+------------+---------------------------
calculator_test | calculator | UTF8 | en_US.utf8 | en_US.utf8 |
calculator_test-0 | calculator | UTF8 | en_US.utf8 | en_US.utf8 |
calculator_test-1 | calculator | UTF8 | en_US.utf8 | en_US.utf8 |
calculator_test-2 | calculator | UTF8 | en_US.utf8 | en_US.utf8 |
calculator_test-3 | calculator | UTF8 | en_US.utf8 | en_US.utf8 |
अब, भले ही आप रेल या मिनी-टेस्ट का उपयोग नहीं कर रहे हों या आपके पास रेल का पुराना संस्करण हो, फिर भी आप समानांतर में परीक्षण चलाते हैं यदि आप उन्हें डॉकर के साथ लिखते हैं। रेल स्वचालित रूप से समानांतर परीक्षणों के लिए डेटाबेस बनाता है, लेकिन अगर कोई अन्य निर्भरताएं हैं, जैसे कि रेडिस या मेमकैच्ड, तो उन्हें मैन्युअल रूप से प्रबंधित करना पड़ सकता है।
चूंकि हमारी सभी निर्भरताएं प्रबंधित हैं, हम समानांतर में परीक्षण चलाने के लिए विभिन्न तर्कों के साथ डॉकर कंपोज़ चला सकते हैं। इस उद्देश्य के लिए, हम निर्दिष्ट कर सकते हैं कि हम किन फ़ोल्डरों पर समानांतर में परीक्षण चलाना चाहते हैं, कई डॉकर कंपोज़ फ़ाइलें बनाएँ, और उन्हें समानांतर में चलाएँ।
आदेशों को सरल बनाने के लिए Makefile जोड़ना
चूंकि हम अपने परीक्षण चलाने के लिए डॉकर और डॉकर कंपोज़ कमांड का उपयोग कर रहे हैं, इसलिए कमांड लंबे हैं। दिन-प्रतिदिन विकास करते समय उन्हें याद रखना और चलाना मुश्किल हो सकता है। इसे एक साधारण कमांड में सरल बनाने के लिए, आइए ऐड मेकफाइल का उपयोग करें। Makefile एक साधारण टेक्स्ट फ़ाइल है जिसका उपयोग लक्ष्य कमांड निष्पादन को संदर्भित करने के लिए किया जाता है।
.PHONY: test
up:
docker-compose up
down:
docker-compose down
test:
docker-compose exec web rails test
हमने मेकफ़ाइल में कुछ कमांड जोड़े हैं। इसे आवेदन के अनुसार आवश्यकतानुसार बढ़ाया जा सकता है। मेकफ़ाइल को रेल एप्लिकेशन की मूल निर्देशिका में जोड़ें। एक बार हमारे पास यह मेकफ़ाइल हो जाने के बाद, हम केवल निम्न आदेश का उपयोग करके परीक्षण चला सकते हैं:
कंटेनरों को बूट करें:
> make up
परीक्षण चलाएँ:
> make test
स्थानीय विकास के लिए Docker का उपयोग करना
हम एप्लिकेशन को विकसित करते समय डॉकर का भी उपयोग कर सकते हैं। यह सुनिश्चित करने में मदद करता है कि एप्लिकेशन परीक्षण, विकास और उत्पादन में लगातार व्यवहार करता है। आइए समीक्षा करें कि स्थानीय विकास के लिए उपरोक्त कंटेनर का उपयोग करने के लिए हमें क्या बदलने की आवश्यकता है।
वॉल्यूम माउंट
एप्लिकेशन को स्थानीय रूप से चलाते समय, हम चाहते हैं कि जब हम कोड में बदलाव करते हैं तो एप्लिकेशन स्थानीय सर्वर में परिवर्तन को प्रतिबिंबित करे। वर्तमान परिदृश्य में, कोड को हमारी मशीन से डॉकर में कॉपी किया जाता है, और सर्वर शुरू हो जाता है। इसलिए, यदि हम स्थानीय मशीन में फ़ाइल में परिवर्तन करते हैं, तो वे डॉकर में परिलक्षित नहीं होते हैं। यह सुनिश्चित करने के लिए कि कोड हमेशा सिंक में है, हम वॉल्यूम माउंट का उपयोग कर सकते हैं।
डॉकर कंपोज़ फ़ाइल में, वॉल्यूम जोड़ें:
version: "3.0"
services:
db:
image: postgres
environment:
POSTGRES_USER: calculator
POSTGRES_PASSWORD: password
POSTGRES_DB: calculator_test
web:
build: .
volumes:
- .:/calculator # Volume mounted
ports:
- "3000:3000"
depends_on:
- db
- sumservice
environment:
CALCULATOR_DATABASE_PASSWORD: password
sumservice:
image: stoplight/prism:4
command: mock -h 0.0.0.0 "/tmp/api.yaml"
volumes:
- ./mock:/tmp/
ports:
- 4010:4010
init: true
अब, यदि हम सेवर में कुछ भी परिवर्तन करते हैं, तो परिवर्तन परिलक्षित होंगे। आइए एक नियंत्रक बनाकर और अपनी योग विधि को कॉल करके इसे आजमाएं:
# controllers/calculation_controller.rb
class CalculationController < ApplicationController
def index
result = Calculation.sum(params[:x], params[:y])
render json: {result: result}
end
end
रूट रूट जोड़ें:
# routes.rb
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
root "calculation#index"
end
अब, अगर हम वापस जाते हैं और ब्राउज़र में ऐप की जांच करते हैं, तो हमें अपेक्षित प्रतिक्रिया मिलती है:
ध्यान दें कि हम नकली sumservice
. का उपयोग करके सर्वर प्रारंभ कर रहे हैं , इसलिए हम क्वेरी पैरामीटर के रूप में URL में जो भी प्रदान करते हैं, वह हमेशा 2 लौटाएगा। यह विकास करने का एक अच्छा तरीका नहीं लगता है, लेकिन नकली सेवा प्रदाता का उपयोग करने के अपने फायदे हैं। माइक्रोसर्विसेज विकसित करते समय, बहुत सारी आश्रित सेवाएँ हो सकती हैं, जिन्हें सेवा शुरू करने से पहले हमें बूट करना होगा। यह विकास के दौरान उत्पादकता बढ़ाने में मदद करता है। हम दूसरी सेवा से संबंधित नहीं हैं और केवल उस सेवा से संबंधित हैं जिसे हम विकसित कर रहे हैं।
यदि हम अंतिम सत्यापन करना चाहते हैं कि यह वास्तविक सेवा के साथ कैसे काम करता है, तो हम एक नई डॉकर कंपोज़ फ़ाइल बनाकर और इसे सेवा की वास्तविक छवि के साथ बदलकर ऐसा कर सकते हैं। यदि यह एक आंतरिक सेवा है, तो हम इसे नवीनतम स्थिर डॉकर छवि के साथ आसानी से बदल सकते हैं। मैं विकास के माहौल में भी नकली सेवा रखने की सलाह दूंगा।
.dockerignore
जैसे-जैसे एप्लिकेशन बड़ा होता है, निर्भरताएं डॉकर बिल्ड संदर्भ को बड़ा करने का कारण बनेंगी। बड़े निर्माण संदर्भ के साथ, डॉकर छवि बनाने में अधिक समय लगता है। यहां तक कि वॉल्यूम माउंट भी एप्लिकेशन के बढ़े हुए आकार के साथ देरी का कारण बन सकता है। इस मामले में, हम अवांछित फ़ाइल को .dockerignore
. में जोड़ सकते हैं बिल्ड संदर्भ को कम करने के लिए फ़ाइल।
.git*
log/*
README.md
node_modules
एंट्रीपॉइंट
जब एक रेल सर्वर एक कंटेनर में चल रहा होता है, तो हमें कभी-कभी यह बताते हुए एक त्रुटि संदेश मिलता है कि सर्वर पहले से चल रहा है क्योंकि कंटेनर से बाहर निकलने पर पीआईडी फ़ाइल को हटाया नहीं गया था। इस त्रुटि को दूर करने के लिए, हम एक ENTRYPOINT जोड़ सकते हैं, जो server.pid
को हटा देगा। फ़ाइल।
FROM ruby:2.7
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -y nodejs yarn
RUN mkdir /calculator
WORKDIR /calculator
COPY Gemfile /calculator/Gemfile
COPY Gemfile.lock /calculator/Gemfile.lock
RUN bundle install
COPY package.json /calculator/package.json
COPY yarn.lock /calculator/yarn.lock
RUN yarn install --check-files
COPY . /calculator
EXPOSE 3000
ENTRYPOINT ./entrypoint.sh
CMD ["rails", "server", "-b", "0.0.0.0"]
entrypoint.sh
बनाएं फ़ाइल:
#!/bin/bash
set -e
# Remove a potentially pre-existing server.pid for Rails.
rm -f /calculator/tmp/pids/server.pid
# Exec the container's main process (CMD command in rails file)
exec "$@"
इसे निष्पादन योग्य बनाएं
chmod +x entrypoint.sh
अब, जब हम डॉकर छवि चलाते हैं, तो हमें इस समस्या का अनुभव नहीं होगा।
निष्कर्ष
एकीकरण परीक्षणों और इकाई परीक्षणों में अंतर करना बहुत महत्वपूर्ण है। इकाई परीक्षण लिखते समय, हम डेटाबेस जैसी बाहरी निर्भरता का मजाक उड़ा सकते हैं। यह अलगाव में कोड का परीक्षण करने में मदद करेगा। मुख्य व्यावसायिक तर्क और उसकी निर्भरता के बीच एकीकरण परीक्षण चलाना भी उतना ही महत्वपूर्ण है। डेटाबेस और बाहरी सेवाओं जैसी निर्भरता को डॉकर और डॉकर कंपोज़ का उपयोग करके एकीकरण में परीक्षण किया जा सकता है। इन दोनों को अलग करना अच्छा अभ्यास है। हमें उन्हें अलग से चलाने में सक्षम होना चाहिए। अधिक यूनिट परीक्षण और कम एकीकरण परीक्षण होने से आपके परीक्षण तेज़ और अधिक विश्वसनीय रूप से चलते हैं।
इस कार्यप्रवाह के कुछ लाभ इस प्रकार हैं:
- इकाई और एकीकरण परीक्षणों के बीच अलगाव।
- चूंकि सभी सीआई सेवाएं कंटेनरों पर चलती हैं, स्थानीय स्तर पर और सीआई में चल रहे परीक्षणों का व्यवहार समान होगा। यह स्थानीय मशीन और सीआई सर्वर में परीक्षण व्यवहार की निरंतरता सुनिश्चित करने में मदद करता है।
- एप्लिकेशन को परिनियोजित करने के लिए कंटेनरों का उपयोग करने से भी उत्पादन सर्वर में एकरूपता सुनिश्चित करने में मदद मिलती है।
- विश्वसनीय परीक्षण, क्योंकि निर्भरता अच्छी तरह से प्रबंधित होती है।
- पोर्टेबल परीक्षण, कई डेवलपर्स द्वारा उपयोग किए जाने पर सेटअप में बहुत कम प्रयास की आवश्यकता होती है।