يساعدك Capybara على اختبار تطبيقات الويب من خلال محاكاة كيفية تفاعل المستخدم الحقيقي مع تطبيقك. إنه لا يعرف برنامج التشغيل الذي يجري اختباراتك ويأتي مع دعم Rack::Test وSelenium المدمج. ويتم دعم WebKit من خلال جوهرة خارجية.
إذا وجدت أنت و/أو شركتك قيمة في Capybara وترغب في المساهمة ماليًا في صيانتها وتطويرها المستمر، يرجى زيارة Patreon
بحاجة الى مساعدة؟ اسأل عن المناقشات (يرجى عدم فتح مشكلة): https://github.com/orgs/teamcapybara/discussions/categories/qa
يتطلب Capybara إصدار Ruby 3.0.0 أو إصدار أحدث. للتثبيت، أضف هذا السطر إلى Gemfile
الخاص بك وقم بتشغيل bundle install
:
gem 'capybara'
إذا كان التطبيق الذي تختبره هو تطبيق Rails، أضف هذا السطر إلى ملف مساعد الاختبار الخاص بك:
require 'capybara/rails'
إذا كان التطبيق الذي تختبره هو تطبيق Rack، وليس Rails، فاضبط Capybara.app على تطبيق Rack الخاص بك:
Capybara . app = MyRackApp
إذا كنت بحاجة إلى اختبار JavaScript، أو إذا كان تطبيقك يتفاعل مع (أو يقع في) عنوان URL بعيد، فستحتاج إلى استخدام برنامج تشغيل مختلف. إذا كنت تستخدم الإصدار 5.0+ من Rails، ولكن لا تستخدم اختبارات نظام Rails من الإصدار 5.1، فربما تريد أيضًا تبديل "الخادم" المستخدم لتشغيل تطبيقك إلى Puma لمطابقة إعدادات Rails الافتراضية.
Capybara . server = :puma # Until your setup is working
Capybara . server = :puma , { Silent : true } # To clean up your test output
تأتي جوهرة cucumber-rails
مع دعم Capybara المدمج. إذا كنت لا تستخدم Rails، فقم بتحميل وحدة capybara/cucumber
يدويًا:
require 'capybara/cucumber'
Capybara . app = MyRackApp
يمكنك استخدام Capybara DSL في خطواتك، كما يلي:
When /I sign in/ do
within ( "#session" ) do
fill_in 'Email' , with : '[email protected]'
fill_in 'Password' , with : 'password'
end
click_button 'Sign in'
end
يمكنك التبديل إلى Capybara.javascript_driver
( :selenium
افتراضيًا) عن طريق وضع علامات على السيناريوهات (أو الميزات) باستخدام @javascript
:
@javascript
Scenario : do something Ajaxy
When I click the Ajax link
...
هناك أيضًا علامات واضحة لكل برنامج تشغيل مسجل تم إعداده لك ( @selenium
و @rack_test
وما إلى ذلك).
قم بتحميل دعم RSpec 3.5+ عن طريق إضافة السطر التالي (عادةً إلى ملف spec_helper.rb
الخاص بك):
require 'capybara/rspec'
إذا كنت تستخدم Rails، فضع مواصفات Capybara الخاصة بك في spec/features
أو spec/system
(يعمل فقط إذا قمت بتكوينها في RSpec) وإذا كانت لديك مواصفات Capybara في دليل مختلف، فقم بوضع علامة على مجموعات الأمثلة بالنوع type: :feature
أو type: :system
اعتمادًا على نوع الاختبار الذي تكتبه.
إذا كنت تستخدم مواصفات نظام Rails، فيرجى الاطلاع على وثائقهم لتحديد برنامج التشغيل الذي ترغب في استخدامه.
إذا كنت لا تستخدم Rails، ضع علامة على جميع مجموعات الأمثلة التي تريد استخدام Capybara فيها type: :feature
.
يمكنك الآن كتابة المواصفات الخاصة بك مثل هذا:
describe "the signin process" , type : :feature do
before :each do
User . create ( email : '[email protected]' , password : 'password' )
end
it "signs me in" do
visit '/sessions/new'
within ( "#session" ) do
fill_in 'Email' , with : '[email protected]'
fill_in 'Password' , with : 'password'
end
click_button 'Sign in'
expect ( page ) . to have_content 'Success'
end
end
استخدم js: true
للتبديل إلى Capybara.javascript_driver
( :selenium
افتراضيًا)، أو قم بتوفير خيار :driver
للتبديل إلى برنامج تشغيل واحد محدد. على سبيل المثال:
describe 'some stuff which requires js' , js : true do
it 'will use the default js driver'
it 'will switch to one specific driver' , driver : :selenium
end
يأتي Capybara أيضًا مزودًا بـ DSL مدمج لإنشاء اختبارات قبول وصفية:
feature "Signing in" do
background do
User . create ( email : '[email protected]' , password : 'caplin' )
end
scenario "Signing in with correct credentials" do
visit '/sessions/new'
within ( "#session" ) do
fill_in 'Email' , with : '[email protected]'
fill_in 'Password' , with : 'caplin'
end
click_button 'Sign in'
expect ( page ) . to have_content 'Success'
end
given ( :other_user ) { User . create ( email : '[email protected]' , password : 'rous' ) }
scenario "Signing in as another user" do
visit '/sessions/new'
within ( "#session" ) do
fill_in 'Email' , with : other_user . email
fill_in 'Password' , with : other_user . password
end
click_button 'Sign in'
expect ( page ) . to have_content 'Invalid email or password'
end
end
feature
هي في الواقع مجرد اسم مستعار describe ..., type: :feature
، background
هي اسم مستعار لـ before
، scenario
it
، و given
/ given!
الأسماء المستعارة لـ let
/ let!
، على التوالى.
وأخيرًا، يتم أيضًا دعم مُطابقات Capybara في مواصفات العرض:
RSpec . describe "todos/show.html.erb" , type : :view do
it "displays the todo title" do
assign :todo , Todo . new ( title : "Buy milk" )
render
expect ( rendered ) . to have_css ( "header h1" , text : "Buy milk" )
end
end
ملاحظة: عندما تحتاج إلى تثبيت أساليب الوكيل 'capybara/rspec' للتغلب على تضارب الأسماء بين أساليب Capybara::DSL all
/ within
ومطابقات RSpec المضمنة ذات الأسماء المتطابقة. إذا اخترت عدم طلب "capybara/rspec"، فيمكنك تثبيت أساليب الوكيل عن طريق طلب "capybara/rspec/matcher_proxies" بعد طلب RSpec و"capybara/dsl"
إذا كنت تستخدم Test::Unit
، فحدد فئة أساسية لاختبارات Capybara الخاصة بك كما يلي:
require 'capybara/dsl'
class CapybaraTestCase < Test :: Unit :: TestCase
include Capybara :: DSL
def teardown
Capybara . reset_sessions!
Capybara . use_default_driver
end
end
إذا كنت تستخدم اختبارات نظام Rails، فيرجى الاطلاع على وثائقها للحصول على معلومات حول اختيار برنامج التشغيل الذي ترغب في استخدامه.
إذا كنت تستخدم Rails، ولكن لا تستخدم اختبارات نظام Rails، فأضف التعليمة البرمجية التالية في ملف test_helper.rb
الخاص بك لجعل Capybara متاحًا في جميع حالات الاختبار المشتقة من ActionDispatch::IntegrationTest
:
require 'capybara/rails'
require 'capybara/minitest'
class ActionDispatch :: IntegrationTest
# Make the Capybara DSL available in all integration tests
include Capybara :: DSL
# Make `assert_*` methods behave like Minitest assertions
include Capybara :: Minitest :: Assertions
# Reset sessions and driver between tests
teardown do
Capybara . reset_sessions!
Capybara . use_default_driver
end
end
إذا كنت لا تستخدم Rails، فحدد فئة أساسية لاختبارات Capybara الخاصة بك كما يلي:
require 'capybara/minitest'
class CapybaraTestCase < Minitest :: Test
include Capybara :: DSL
include Capybara :: Minitest :: Assertions
def teardown
Capybara . reset_sessions!
Capybara . use_default_driver
end
end
تذكر أن تتصل super
في أي فئات فرعية تتجاوز teardown
.
لتبديل برنامج التشغيل، قم بتعيين Capybara.current_driver
. على سبيل المثال،
class BlogTest < ActionDispatch :: IntegrationTest
setup do
Capybara . current_driver = Capybara . javascript_driver # :selenium by default
end
test 'shows blog posts' do
# ... this test is run with Selenium ...
end
end
اتبع الإرشادات المذكورة أعلاه لـ Minitest واطلب بالإضافة إلى ذلك capybara/minitest/spec
page . must_have_content ( 'Important!' )
يستخدم Capybara نفس DSL لتشغيل مجموعة متنوعة من المتصفحات وبرامج التشغيل مقطوعة الرأس.
افتراضيًا، يستخدم Capybara برنامج التشغيل :rack_test
، وهو سريع ولكنه محدود: فهو لا يدعم JavaScript، ولا يمكنه الوصول إلى موارد HTTP خارج تطبيق Rack الخاص بك، مثل واجهات برمجة التطبيقات البعيدة وخدمات OAuth. للتغلب على هذه القيود، يمكنك إعداد برنامج تشغيل افتراضي مختلف لميزاتك. على سبيل المثال، إذا كنت تفضل تشغيل كل شيء في السيلينيوم، فيمكنك القيام بما يلي:
Capybara . default_driver = :selenium # :selenium_chrome and :selenium_chrome_headless are also registered
ومع ذلك، إذا كنت تستخدم RSpec أو Cucumber (وتطبيقك يعمل بشكل صحيح بدون JS)، فقد ترغب بدلاً من ذلك في التفكير في ترك :rack_test
الأسرع باعتباره default_driver ، ووضع علامة فقط على تلك الاختبارات التي تتطلب برنامج تشغيل قادر على JavaScript باستخدام js: true
أو @javascript
على التوالي. افتراضيًا، يتم تشغيل اختبارات JavaScript باستخدام برنامج التشغيل :selenium
. يمكنك تغيير ذلك عن طريق تعيين Capybara.javascript_driver
.
يمكنك أيضًا تغيير برنامج التشغيل مؤقتًا (عادةً في الكتل قبل/الإعداد وبعد/التفكيك):
Capybara . current_driver = :selenium # temporarily select different driver
# tests here
Capybara . use_default_driver # switch back to default driver
ملاحظة : يؤدي تبديل برنامج التشغيل إلى إنشاء جلسة عمل جديدة، لذا قد لا تتمكن من التبديل في منتصف الاختبار.
RackTest هو برنامج التشغيل الافتراضي لـ Capybara. إنه مكتوب بلغة روبي خالصة ولا يحتوي على أي دعم لتنفيذ JavaScript. نظرًا لأن برنامج التشغيل RackTest يتفاعل مباشرة مع واجهات Rack، فإنه لا يتطلب بدء تشغيل الخادم. ومع ذلك، هذا يعني أنه إذا كان تطبيقك ليس تطبيق Rack (Rails وSinatra ومعظم أطر عمل Ruby الأخرى هي تطبيقات Rack)، فلن تتمكن من استخدام برنامج التشغيل هذا. علاوة على ذلك، لا يمكنك استخدام برنامج تشغيل RackTest لاختبار تطبيق بعيد، أو للوصول إلى عناوين URL البعيدة (على سبيل المثال، عمليات إعادة التوجيه إلى مواقع خارجية، أو واجهات برمجة التطبيقات الخارجية، أو خدمات OAuth) التي قد يتفاعل معها تطبيقك.
يوفر capybara-mechanize برنامج تشغيل مشابه يمكنه الوصول إلى الخوادم البعيدة.
يمكن تكوين RackTest بمجموعة من الرؤوس مثل هذا:
Capybara . register_driver :rack_test do | app |
Capybara :: RackTest :: Driver . new ( app , headers : { 'HTTP_USER_AGENT' => 'Capybara' } )
end
راجع القسم الخاص بإضافة برامج التشغيل وتكوينها.
يدعم Capybara السيلينيوم 3.5+ (برنامج تشغيل الويب). من أجل استخدام السيلينيوم، ستحتاج إلى تثبيت جوهرة selenium-webdriver
، وإضافتها إلى ملف Gemfile الخاص بك إذا كنت تستخدم المجمع.
يقوم Capybara بالتسجيل المسبق لعدد من برامج التشغيل المسماة التي تستخدم السيلينيوم - وهي:
يجب أن تعمل هذه (مع تثبيت البرامج ذات الصلة) في تكوين سطح المكتب المحلي ولكن قد تحتاج إلى تخصيصها إذا كنت تستخدمها في بيئة CI حيث قد يلزم تمرير خيارات إضافية إلى المتصفحات. راجع القسم الخاص بإضافة برامج التشغيل وتكوينها.
ملاحظة : قد لا تشارك برامج التشغيل التي تقوم بتشغيل الخادم في سلسلة رسائل مختلفة نفس المعاملة مثل اختباراتك، مما يتسبب في عدم مشاركة البيانات بين خادم الاختبار وخادم الاختبار، راجع المعاملات وإعداد قاعدة البيانات أدناه.
مرجع كامل متاح في Rubydoc.info .
ملاحظة: افتراضيًا، سيحدد Capybara العناصر المرئية فقط. وذلك لأن المستخدم الحقيقي لن يتمكن من التفاعل مع العناصر غير المرئية.
ملاحظة : جميع عمليات البحث في Capybara حساسة لحالة الأحرف . وذلك لأن Capybara يستخدم XPath بشكل كبير، والذي لا يدعم حساسية حالة الأحرف.
يمكنك استخدام طريقة الزيارة للانتقال إلى الصفحات الأخرى:
visit ( '/projects' )
visit ( post_comments_path ( post ) )
تأخذ طريقة الزيارة معلمة واحدة فقط، وتكون طريقة الطلب دائمًا هي GET.
يمكنك الحصول على المسار الحالي لجلسة التصفح واختباره باستخدام أداة مطابقة have_current_path
:
expect ( page ) . to have_current_path ( post_comments_path ( post ) )
ملاحظة : يمكنك أيضًا تأكيد المسار الحالي عن طريق اختبار قيمة current_path
مباشرة. ومع ذلك، يعد استخدام مُطابق have_current_path
أكثر أمانًا لأنه يستخدم سلوك انتظار Capybara لضمان اكتمال الإجراءات السابقة (مثل click_link
).
المرجع الكامل: كابيبارا :: العقدة :: الإجراءات
يمكنك التفاعل مع تطبيق الويب باتباع الروابط والأزرار. يتبع Capybara تلقائيًا أي عمليات إعادة توجيه، ويرسل النماذج المرتبطة بالأزرار.
click_link ( 'id-of-link' )
click_link ( 'Link Text' )
click_button ( 'Save' )
click_on ( 'Link Text' ) # clicks on either links or buttons
click_on ( 'Button Value' )
المرجع الكامل: كابيبارا :: العقدة :: الإجراءات
هناك عدد من الأدوات للتفاعل مع عناصر النموذج:
fill_in ( 'First Name' , with : 'John' )
fill_in ( 'Password' , with : 'Seekrit' )
fill_in ( 'Description' , with : 'Really Long Text...' )
choose ( 'A Radio Button' )
check ( 'A Checkbox' )
uncheck ( 'A Checkbox' )
attach_file ( 'Image' , '/path/to/image.jpg' )
select ( 'Option' , from : 'Select Box' )
المرجع الكامل: Capybara::Node::Matchers
يحتوي Capybara على مجموعة غنية من الخيارات للاستعلام عن الصفحة لوجود عناصر معينة، والعمل مع تلك العناصر ومعالجتها.
page . has_selector? ( 'table tr' )
page . has_selector? ( :xpath , './/table/tr' )
page . has_xpath? ( './/table/tr' )
page . has_css? ( 'table tr.foo' )
page . has_content? ( 'foo' )
ملاحظة: النماذج السلبية مثل has_no_selector?
تختلف عن not has_selector?
. اقرأ القسم الخاص بجافا سكريبت غير المتزامن للحصول على شرح.
يمكنك استخدامها مع أدوات التطابق السحرية الخاصة بـ RSpec:
expect ( page ) . to have_selector ( 'table tr' )
expect ( page ) . to have_selector ( :xpath , './/table/tr' )
expect ( page ) . to have_xpath ( './/table/tr' )
expect ( page ) . to have_css ( 'table tr.foo' )
expect ( page ) . to have_content ( 'foo' )
المرجع الكامل: كابيبارا::عقدة::Finders
يمكنك أيضًا العثور على عناصر محددة للتلاعب بها:
find_field ( 'First Name' ) . value
find_field ( id : 'my_field' ) . value
find_link ( 'Hello' , :visible => :all ) . visible?
find_link ( class : [ 'some_class' , 'some_other_class' ] , :visible => :all ) . visible?
find_button ( 'Send' ) . click
find_button ( value : '1234' ) . click
find ( :xpath , ".//table/tr" ) . click
find ( "#overlay" ) . find ( "h1" ) . click
all ( 'a' ) . each { | a | a [ :href ] }
إذا كنت بحاجة إلى العثور على عناصر من خلال سمات/خصائص إضافية، فيمكنك أيضًا تمرير كتلة التصفية، والتي سيتم فحصها داخل سلوك الانتظار العادي. إذا وجدت نفسك بحاجة إلى استخدام هذا كثيرًا، فقد يكون من الأفضل إضافة محدد مخصص أو إضافة مرشح إلى محدد موجود.
find_field ( 'First Name' ) { | el | el [ 'data-xyz' ] == '123' }
find ( "#img_loading" ) { | img | img [ 'complete' ] == true }
ملحوظة : سينتظر find
حتى يظهر العنصر على الصفحة، كما هو موضح في قسم Ajax. إذا لم يظهر العنصر فإنه سوف يثير خطأ.
تحتوي جميع هذه العناصر على جميع طرق Capybara DSL المتاحة، لذا يمكنك قصرها على أجزاء معينة من الصفحة:
find ( '#navigation' ) . click_link ( 'Home' )
expect ( find ( '#navigation' ) ) . to have_button ( 'Sign out' )
يتيح Capybara إمكانية تقييد إجراءات معينة، مثل التفاعل مع النماذج أو النقر على الروابط والأزرار، داخل منطقة معينة من الصفحة. لهذا الغرض، يمكنك استخدام الطريقة العامة . اختياريًا، يمكنك تحديد نوع المحدد الذي تريد استخدامه.
within ( "li#employee" ) do
fill_in 'Name' , with : 'Jimmy'
end
within ( :xpath , ".//li[@id='employee']" ) do
fill_in 'Name' , with : 'Jimmy'
end
توجد طرق خاصة لتقييد النطاق بمجموعة حقول محددة، يتم تحديدها بواسطة معرف أو نص علامة التسمية التوضيحية لمجموعة الحقول، وجدول محدد، يتم تعريفه إما بواسطة معرف أو نص علامة التسمية التوضيحية للجدول.
within_fieldset ( 'Employee' ) do
fill_in 'Name' , with : 'Jimmy'
end
within_table ( 'Employee' ) do
fill_in 'Name' , with : 'Jimmy'
end
يوفر Capybara بعض الطرق لتسهيل البحث عن النوافذ وتبديلها:
facebook_window = window_opened_by do
click_button 'Like'
end
within_window facebook_window do
find ( '#login_email' ) . set ( '[email protected]' )
find ( '#login_password' ) . set ( 'qwerty' )
click_button 'Submit'
end
في برامج التشغيل التي تدعمها، يمكنك بسهولة تنفيذ JavaScript:
page . execute_script ( "$('body').empty()" )
بالنسبة للتعبيرات البسيطة، يمكنك إرجاع نتيجة البرنامج النصي.
result = page . evaluate_script ( '4 + 4' ) ;
بالنسبة للنصوص الأكثر تعقيدًا، ستحتاج إلى كتابتها كتعبير واحد.
result = page . evaluate_script ( <<~JS , 3 , element )
(function(n, el){
var val = parseInt(el.value, 10);
return n+val;
})(arguments[0], arguments[1])
JS
وفي برامج التشغيل التي تدعمها، يمكنك قبول التنبيهات والتأكيدات والمطالبات ورفضها والرد عليها.
يمكنك قبول رسائل التنبيه عن طريق تغليف الكود الذي ينتج تنبيهًا في كتلة:
accept_alert 'optional text or regex' do
click_link ( 'Show Alert' )
end
يمكنك قبول التأكيد أو رفضه عن طريق تغليفه في كتلة أيضًا:
accept_confirm 'optional text' do
click_link ( 'Show Confirm' )
end
dismiss_confirm 'optional text' do
click_link ( 'Show Confirm' )
end
يمكنك أيضًا قبول المطالبات أو رفضها، وكذلك تقديم نص لملء الرد:
accept_prompt ( 'optional text' , with : 'Linus Torvalds' ) do
click_link ( 'Show Prompt About Linux' )
end
dismiss_prompt ( 'optional text' ) do
click_link ( 'Show Prompt About Linux' )
end
تقوم كافة الأساليب المشروطة بإرجاع الرسالة التي تم تقديمها. لذلك، يمكنك الوصول إلى رسالة المطالبة عن طريق تعيين الإرجاع لمتغير:
message = accept_prompt ( with : 'Linus Torvalds' ) do
click_link ( 'Show Prompt About Linux' )
end
expect ( message ) . to eq ( 'Who is the chief architect of Linux?' )
قد يكون من المفيد التقاط لقطة للصفحة كما هي حاليًا وإلقاء نظرة عليها:
save_and_open_page
يمكنك أيضًا استرداد الحالة الحالية لـ DOM كسلسلة باستخدام page.html .
print page . html
وهذا مفيد في الغالب لتصحيح الأخطاء. يجب عليك تجنب الاختبار مقابل محتويات page.html
واستخدام أساليب البحث الأكثر تعبيرًا بدلاً من ذلك.
وأخيرًا، في برامج التشغيل التي تدعمه، يمكنك حفظ لقطة شاشة:
page . save_screenshot ( 'screenshot.png' )
أو قم بحفظه وفتحه تلقائيًا:
save_and_open_screenshot
يتم حفظ لقطات الشاشة في Capybara.save_path
، نسبة إلى دليل التطبيق. إذا كنت تطلب capybara/rails
، فسيكون Capybara.save_path
افتراضيًا على tmp/capybara
.
يتشارك المساعدون والمطابقون الذين يقبلون المحددات في توقيع أسلوب شائع يتضمن:
عادةً ما تكون هذه الوسائط اختيارية بطريقة أو بأخرى.
تحدد وسيطة الاسم المحدد الذي سيتم استخدامه. يكون الوسيط اختياريًا عندما ينقل المساعد اسم المحدد بشكل صريح (على سبيل المثال، يستخدم find_field
:field
، ويستخدم find_link
:link
، وما إلى ذلك):
page . html # => '<a href="/">Home</a>'
page . find ( :link ) == page . find_link
page . html # => '<input>'
page . find ( :field ) == page . find_field
عادةً ما تمثل وسيطة محدد الموقع المعلومات التي يمكنها التمييز بشكل أكثر وضوحًا بين العنصر الذي يطابق المحدد والعنصر الذي لا:
page . html # => '<div id="greeting">Hello world</div>'
page . find ( :css , 'div' ) . text # => 'Hello world'
page . find ( :xpath , './/div' ) . text # => 'Hello world'
يمكن لطرق البحث ذات الأغراض العامة مثل find
و all
قبول محدد المواقع كوسيطة موضعية أولى عندما تتمكن الطريقة من استنتاج القيمة الافتراضية من تكوين Capybara.default_selector
: