Rspec-core: Pertimbangkan kembali `shared_context_metadata_behavior`

Dibuat pada 27 Des 2020  ·  5Komentar  ·  Sumber: rspec/rspec-core

Latar belakang

Kami memiliki masalah dengan metadata yang ditentukan pada grup contoh bersama spec-local ( shared_examples / shared_examples_for / shared_context ) yang menyebabkan mereka dimasukkan dalam grup contoh yang sama sekali tidak terkait yang dilaporkan di [ 1 ]/[ 2 ]. Beberapa informasi lebih lanjut di https://github.com/rspec/rspec-core/issues/1762.

Dalam https://github.com/rspec/rspec-core/issues/1790 (https://github.com/rspec/rspec-core/commit/ed2d59c8a97d32f4a20e91d0abdad87f90d2b930), shared_context_metadata_behavior dengan non-default :apply_to_host_groups nilai. https://github.com/rspec/rspec-core/commit/3589ab577d09db88ef5d5f0d60e8c35bfc55691f menambahkannya ke penginisialisasi proyek bersama dengan catatan bahwa itu akan menjadi default dan satu-satunya opsi di RSpec 4.

:trigger_inclusion tetap menjadi pengaturan default , karena alasan SemVer.

Pendeknya:

`:trigger_inclusion`: shared context will be implicitly included in any groups (or examples) that have matching metadata.
`:apply_to_host_groups`: the metadata will be inherited by the metadata hash of all host groups and examples.
### Penggunaan Secara pribadi, saya belum pernah melihat `:apply_to_Host_groups` digunakan seperti yang dirancang. Di sisi lain, saya telah melihat beberapa proyek menggunakan `:trigger_inclusion` untuk grup/konteks bersama yang ditentukan secara global. Tapi itu sampel satu. Mari kita periksa. Sebagai sandbox untuk polisi `rubocop-rspec` baru, saya telah mengumpulkan daftar proyek Ruby yang paling banyak bintangnya yang menggunakan RSpec, [`real-world-rspec`](https://github.com/pirj/real-world -rspec), ~ total 35 proyek. Dari 35 tersebut (termasuk repo RSpec juga!), 7 menggunakan `:apply_to_Host_groups` di pembantu spesifikasi mereka: 24pullrequests/ administrate/ Homebrew/ camaleon-cms/ canvas-lms/ capistrano/ capybara/ cartodb/ chatwoot/ chef/ diaspora / wacana/ locomotivecms/ errbit/ fat_free_crm/ forem/ gitlabhq/ hound/ huginn/ lobsters/ loomio/ mastodon/ open-source-billing/ publify/ wayang/ radian/ refinerycms/ rspec-core/ rspec-expectations/ rspec-mock/ rspec -rails/ rubocop/ rubytoolbox/ sharetribe/ solidus/ foya/
engine/spec/spec_helper.rb|48| 10:  config.shared_context_metadata_behavior = :apply_to_host_groups
rspec-rails/spec/spec_helper.rb|56| 10:  config.shared_context_metadata_behavior = :apply_to_host_groups
lobsters/spec/spec_helper.rb|45| 10:  config.shared_context_metadata_behavior = :apply_to_host_groups
rubytoolbox/spec/spec_helper.rb|49| 10:  config.shared_context_metadata_behavior = :apply_to_host_groups
forem/spec/spec_helper.rb|58| 10:  config.shared_context_metadata_behavior = :apply_to_host_groups
gitlabhq/qa/spec/spec_helper.rb|56| 10:  config.shared_context_metadata_behavior = :apply_to_host_groups
chatwoot/spec/spec_helper.rb|16| 10:  config.shared_context_metadata_behavior = :apply_to_host_groups
Dan satu di `lib`:
capybara/lib/capybara/spec/spec_helper.rb|19| 16:        config.shared_context_metadata_behavior = :apply_to_host_groups
Lainnya, karena mereka tidak memiliki setelan ini dan defaultnya adalah `:trigger_inclusion`, jangan gunakan metadata grup contoh bersama, atau andalkan pemicu penyertaan.
Mari kita lihat kegunaannya. Buka spoiler ini untuk melihat **semua** 40 grup/konteks bersama dengan metadata (dari ~3000 total grup bersama)
 rspec-core/spec/rspec/core/metadata_spec.rb|317| 42: RSpec.shared_examples_for("beberapa perilaku bersama", :include_it => true) lakukan
 wayang/spec/shared_contexts/digests.rb|16| 1:shared_context('dengan algoritma intisari yang didukung', :uses_checksums => true) lakukan
 wayang/spec/shared_contexts/digests.rb|27| 1:shared_context("ketika digest_algorithm disetel ke sha256", :digest_algorithm => 'sha256') lakukan
 wayang/spec/shared_contexts/digests.rb|42| 1:shared_context("ketika digest_algorithm disetel ke md5", :digest_algorithm => 'md5') lakukan
 wayang/spec/shared_contexts/digests.rb|57| 1:shared_context("ketika digest_algorithm disetel ke sha512", :digest_algorithm => 'sha512') lakukan
 wayang/spec/shared_contexts/digests.rb|72| 1:shared_context("ketika digest_algorithm disetel ke sha384", :digest_algorithm => 'sha384') lakukan
 wayang/spec/shared_contexts/digests.rb|87| 1:shared_context("ketika digest_algorithm disetel ke sha224", :digest_algorithm => 'sha224') lakukan
 diaspora/spec/support/gon.rb|3| 1:konteks_berbagi :gon do
 diaspora/spec/spec_helper.rb|163| 1:shared_context suppress_csrf_verification: :none do
 rubocop/lib/rubocop/rspec/shared_contexts.rb|5| 7:RSpec.shared_context 'lingkungan terisolasi', :isolated_environment do
 rubocop/lib/rubocop/rspec/shared_contexts.rb|43| 7:RSpec.shared_context 'maintain registry', :restore_registry do
 rubocop/lib/rubocop/rspec/shared_contexts.rb|56| 7:RSpec.shared_context 'config', :config do # rubocop:disable Metrics/BlockLength
 rubocop/lib/rubocop/rspec/shared_contexts.rb|114| 7:RSpec.shared_context 'keluaran konsol tiruan' lakukan
 rubocop/lib/rubocop/rspec/shared_contexts.rb|126| 7:RSpec.shared_context 'ruby 2.4', :ruby24 do
 rubocop/lib/rubocop/rspec/shared_contexts.rb|130| 7:RSpec.shared_context 'ruby 2.5', :ruby25 do
 rubocop/lib/rubocop/rspec/shared_contexts.rb|134| 7:RSpec.shared_context 'ruby 2.6', :ruby26 do
 rubocop/lib/rubocop/rspec/shared_contexts.rb|138| 7:RSpec.shared_context 'ruby 2.7', :ruby27 do
 rubocop/lib/rubocop/rspec/shared_contexts.rb|142| 7:RSpec.shared_context 'ruby 3.0', :ruby30 do
 brew/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb|34| 7:RSpec.shared_context "Homebrew Cask", :needs_macos do
 chef/spec/support/shared/functional/securable_resource.rb|78| 1:shared_context "gunakan izin Windows", :windows_only do
 canvas-lms/spec/lib/turnitin/turnitin_spec_helper.rb|22| 7:RSpec.shared_context "shared_tii_lti", :shared_context => :metadata do
 canvas-lms/spec/lib/turnitin/turnitin_spec_helper.rb|22| 41:RSpec.shared_context "shared_tii_lti", :shared_context => :metadata do
 canvas-lms/spec/lti2_course_spec_helper.rb|22| 7:RSpec.shared_context "lti2_course_spec_helper", :shared_context => :metadata do
 canvas-lms/spec/lti2_course_spec_helper.rb|22| 50:RSpec.shared_context "lti2_course_spec_helper", :shared_context => :metadata do
 canvas-lms/spec/plagiarism_platform_spec_helper.rb|22| 7:RSpec.shared_context "plagiarism_platform", :shared_context => :metadata do
 canvas-lms/spec/plagiarism_platform_spec_helper.rb|22| 46:RSpec.shared_context "plagiarism_platform", :shared_context => :metadata do
 canvas-lms/spec/lti2_spec_helper.rb|22| 7:RSpec.shared_context "lti2_spec_helper", :shared_context => :metadata do
 canvas-lms/spec/lti2_spec_helper.rb|22| 43:RSpec.shared_context "lti2_spec_helper", :shared_context => :metadata do
 canvas-lms/spec/lti_1_3_tool_configuration_spec_helper.rb|22| 7:RSpec.shared_context "lti_1_3_tool_configuration_spec_helper", shared_context: :metadata do
 canvas-lms/spec/lti_1_3_tool_configuration_spec_helper.rb|22| 64:RSpec.shared_context "lti_1_3_tool_configuration_spec_helper", shared_context: :metadata do
 canvas-lms/spec/lti_1_3_spec_helper.rb|23| 7:RSpec.shared_context "lti_1_3_spec_helper", shared_context: :metadata do
 canvas-lms/spec/lti_1_3_spec_helper.rb|23| 45:RSpec.shared_context "lti_1_3_spec_helper", shared_context: :metadata do
 canvas-lms/spec/apis/lti/lti2_api_spec_helper.rb|24| 7:RSpec.shared_context "lti2_api_spec_helper", :shared_context => :metadata do
 canvas-lms/spec/apis/lti/lti2_api_spec_helper.rb|24| 47:RSpec.shared_context "lti2_api_spec_helper", :shared_context => :metadata do
 gitlabhq/spec/lib/gitlab/git/merge_base_spec.rb|11| 3: shared_context 'referensi yang ada dengan basis gabungan', : existing_refs do
 gitlabhq/spec/lib/gitlab/git/merge_base_spec.rb|17| 3: shared_context 'ketika melewati ref yang hilang', :missing_ref do
 gitlabhq/spec/lib/gitlab/git/merge_base_spec.rb|23| 3: shared_context 'ketika melewati referensi yang tidak memiliki nenek moyang yang sama', :no_common_ancestor lakukan
 gitlabhq/spec/lib/gitlab/ci/config/entry/retry_spec.rb|8| 3: shared_context 'ketika retry value adalah numerik', :numeric do
 gitlabhq/spec/lib/gitlab/ci/config/entry/retry_spec.rb|13| 3: shared_context 'ketika nilai coba lagi adalah hash', :hash do
 rspec-expectations/spec/spec_helper.rb|72| 7:RSpec.shared_context "dengan #harus diaktifkan", :uses_should do
 rspec-expectations/spec/spec_helper.rb|99| 7:RSpec.shared_context "dengan #harus diaktifkan secara eksklusif", :uses_only_should do
 rspec-expectations/spec/spec_helper.rb|120| 7:RSpec.shared_context "dengan warn_about_potential_false_positives disetel ke false", :warn_about_potential_false_positives lakukan

Jika kita membuat perpotongan dengan list sebelumnya (rspec-rails, lobsters, rubytoolbox, forem, gitlabhq, chatwoot), ternyata tidak ada project yang menggunakan :apply_to_host_groups .
gitlabhq mungkin sedikit membingungkan, mereka sebenarnya memiliki dua pembantu spesifikasi, gitlabhq/qa/spec/spec_helper.rb dan gitlabhq/spec/spec_helper.rb .
Dan mereka menggunakan :trigger_inclusion :

  shared_context 'existing refs with a merge base', :existing_refs do
    let(:refs) do
      %w(304d257dcb821665ab5110318fc58a007bd104ed 0031876facac3f2b2702a0e53a26e89939a42209)
    end
  end

  describe '#sha' do
    context 'when the refs exist', :existing_refs do

dalam spesifikasi mereka.

Kami juga menggunakannya. rspec-expectations :

RSpec.shared_context "with warn_about_potential_false_positives set to false", :warn_about_potential_false_positives do
  original_value = RSpec::Expectations.configuration.warn_about_potential_false_positives?

  after(:context)  { RSpec::Expectations.configuration.warn_about_potential_false_positives = original_value }
end

Kesimpulan awal: proyek Ruby populer yang menggunakan RSpec yang mengonfigurasi shared_context_metadata_behavior ke :apply_to_host_groups melakukan ini secara membabi buta dan tidak pernah menggunakannya.

semantik

Kami memiliki dua cara untuk memasukkan grup bersama. include_context / include_examples dan it_behaves_like . Yang terakhir membuat grup bersarang.

Tidak masuk akal untuk menerapkan metadata yang ditentukan untuk grup bersarang yang dibuat secara implisit.

Di sisi lain, sama seperti dengan beberapa let yang didefinisikan dalam konteks yang disertakan berbeda, metadata, jika diterapkan dari konteks yang disertakan berbeda, memiliki peluang untuk menimpa satu sama lain, dan kami tidak mencetak peringatan untuk kasus ini , meninggalkan ruang untuk kebingungan.

Jika kami menghapus :trigger_inclusion , apa yang akan kami sarankan untuk menggantinya? Misalnya untuk grup bersama yang ditentukan secara global:

Untuk grup bersama yang ditentukan secara global, ini berfungsi:

RSpec.shared_examples 'it is odd' do
  it { is_expected.to be_odd }
end

RSpec.configure do |config|
  config.include_context 'it is odd', :odd
end

RSpec.describe do
  context 'odd', :odd do
    subject { 1 }
  end
end

Namun, mengapa include_context ?
Yah, kita hanya memiliki include_context pada objek Configuration . Tidak ada include_examples atau it_behaves_like sana.

Penggunaan yang lebih umum dan dibuat-buat:

config.include_context "example guest user", :type => :request

Tapi, apa yang harus dijanjikan sebagai imbalan untuk grup bersama yang ditentukan secara lokal?
Terkadang, cukup sulit untuk memanggil include_context / it_behaves_like , dan penyertaan implisit melalui metadata yang cocok berguna untuk membuat segalanya kering. Dengan biaya sedikit sihir. Metadata RSpec mana yang dimaksud.

Pendapat tidak populer

Tidak diragukan lagi bahwa opsi ini telah memecahkan masalah dengan dimasukkannya contoh bersama yang didefinisikan dalam ruang lingkup yang sama sekali tidak terkait.

Namun, apakah ada alasan bagus untuk "menerapkan metadata ke grup host"? Apakah itu digunakan? Apakah itu berguna? Bukankah itu membingungkan?

Usul

Saya menyarankan:

  • simpan opsi shared_context_metadata_behavior bersama dengan nilai default :trigger_inclusion
  • menghapus gagasan tentang penghinaan

... rilis 4.0

  • perbaiki masalah dengan penyertaan yang salah ( bukti konsep )
  • ubah penginisialisasi proyek, hapus catatan penghentian, dan gunakan :trigger_inclusion sebagai default
  • mencela :apply_to_host_groups

Jika kita mempertahankan :trigger_inclusion sebagai default, sebagian besar perilaku tidak akan berubah. Kurang tiket.

Keraguan

Mungkin memerlukan perbaikan yang signifikan untuk memperbaiki penyertaan, sampai pada titik di mana hal itu hampir tidak mungkin dilakukan.
Saya masih berharap kenyataan tidak akan menghancurkan impian masa muda saya yang terlalu optimis, dan itu bisa dilakukan.

Komentar yang paling membantu

Terima kasih telah menulis ini @pirj dan memanggil saya untuk berkomentar :).

Saya masih berpikir bahwa penyertaan implisit dari grup contoh bersama melalui metadata masih memiliki masalah. #1790 menguraikan masalah yang saya lihat dengannya ketika saya menulis masalah itu. Secara keseluruhan, perilaku inklusi implisit terasa tidak konsisten dengan RSpec lainnya, IMO; pertimbangkan bahwa semua cara lain yang memanfaatkan metadata RSpec, Anda mengonfigurasinya di blok RSpec.configure . Memiliki 1 fitur RSpec menggunakan metadata secara implisit (tanpa mengharuskan pengguna untuk mengonfigurasinya secara eksplisit dalam RSpec.configure ) adalah sesuatu yang saya harapkan akan membingungkan pengguna yang telah menggunakan metadata RSpec tetapi tidak mengetahui perilaku penyertaan implisit . Baik rspec-rails#1579 dan rspec-rails#1241 adalah contohnya: pengguna menandai grup contoh bersama mereka dengan metadata, mengharapkannya untuk bertindak seperti metadata pada tindakan grup normal (mis. memicu penyertaan config.include 'd modul, tersedia untuk pemfilteran, dll) dan terkejut melihat perilakunya tidak seperti itu. Faktanya, mereka sangat terkejut dengan hal itu sehingga mereka melaporkannya sebagai bug meskipun berfungsi seperti yang dirancang. Itu menunjukkan kepada saya bahwa itu adalah desain yang buruk untuk memulai: jika itu benar-benar selaras dengan RSpec lainnya, itu tidak akan mengarahkan pengguna untuk melaporkannya sebagai bug.

Sebagai kotak pasir untuk polisi rubocop-rspec baru, saya telah mengumpulkan daftar proyek Ruby yang paling banyak bintangnya yang menggunakan RSpec, rspec dunia nyata, ~ total 35 proyek. Dari 35 itu (termasuk repo RSpec juga!), 7 menggunakan :apply_to_host_groups di pembantu spesifikasi mereka:

Semantik yang tepat untuk menandai grup contoh bersama dengan metadata adalah sesuatu yang saya harapkan 99% dari pengguna RSpec tidak pernah memikirkan dan situasi membingungkan yang dipecahkan oleh perilaku yang lebih baru relatif jarang .... jadi saya tidak terkejut dengan itu sama sekali. TBH, saya menduga :apply_to_host_groups mungkin terutama digunakan oleh proyek yang menghasilkan (atau membuat ulang) spec_helper.rb setelah kami mengubah kode konfigurasi spec_helper.rb dihasilkan di 3589ab577d09db88ef5d5f0d60e8c35bfc55691f.

Untuk pengguna yang ingin memicu penyertaan grup contoh bersama berdasarkan metadata, disediakan API config.include_context yang, IMO, lebih sederhana, lebih konsisten, dan lebih eksplisit yang melakukannya secara otomatis untuk pengguna karena mereka menandai grup bersama dan grup normal dengan metadata yang sama. AFAIK, tidak ada yang disediakan :trigger_inclusion yang tidak dapat dicapai oleh pengguna yang menggunakan config.include_context secara eksplisit. (Jika ada sesuatu yang tidak dapat dicapai dengan cara itu, beri tahu saya!). OTOH, jika pengguna ingin menandai grup contoh bersama mereka dengan beberapa metadata, dan menerapkannya di mana pun grup bersama disertakan...Saya tidak berpikir ada mekanisme alternatif untuk ini. (Sebenarnya, mungkin config.define_derived_metadata dapat digunakan untuk mensimulasikan ini, tetapi IMO yang terasa seperti "menyelesaikan" untuk fitur yang kurang).

Secara pribadi, saya belum pernah melihat :apply_to_Host_groups digunakan seperti yang dirancang.

Inilah cara saya menggunakannya:

  • Saya telah menandai sementara grup contoh bersama dengan :focus , :pending , atau :skipped sehingga saya dapat fokus pada (atau memfilter) spesifikasi yang bergantung pada contoh bersama tertentu kelompok. Grup contoh bersama umumnya berarti ada beberapa masalah lintas sektoral yang berlaku untuk semua grup termasuk, dan dapat menjalankan hanya spesifikasi tersebut (atau mengecualikan spesifikasi tersebut) bisa sangat berguna. Perlu dicatat bahwa penggunaan fitur ini umumnya tidak akan muncul dalam kode yang dikomit untuk proyek apa pun, karena :focus , :skip dan :pending biasanya merupakan perubahan sementara yang tidak berkomitmen (terutama :focus ).
  • Ini bisa sangat berguna sebagai cara untuk mengekspresikan dependensi pada kode test harness lainnya. Misalnya, pertimbangkan sebuah proyek yang secara kondisional membungkus contoh dalam transaksi DB ketika mereka diberi tag :db . (Hal ini dapat dicapai dengan mendefinisikan DB support misalnya kelompok bersama dengan tepat around hook, dan kemudian menggunakan config.include_context "DB support", :db ). Sekarang bayangkan pengembang ingin mendefinisikan grup contoh bersama baru bernama logged in as admin yang mendefinisikan kait before yang membuat pengguna admin dalam database dan masuk sebagai pengguna tersebut menggunakan uji rak atau apa pun . Karena grup contoh bersama yang baru ini berinteraksi dengan database di hook before , ia memiliki ketergantungan pada grup contoh bersama DB support . IMO, cara terbersih untuk mengekspresikan ketergantungan ini adalah dengan menandai grup contoh bersama logged in as admin dengan :db sehingga dukungan DB diterapkan secara otomatis ketika logged in as an admin disertakan dalam grup host . Anda dapat melakukan include_context 'DB support' di grup contoh logged in as an admin untuk menerapkan transaksi DB secara otomatis, tetapi jika cara "normal" Anda mengelolanya di tempat lain adalah melalui tag :db itu aneh untuk tidak dapat melakukannya di sini.

Kami juga menggunakannya. rspec-harapan:

TERTAWA TERBAHAK-BAHAK :). Saya tidak terlalu terkejut dengan itu; kami belum secara historis memutakhirkan RSpec ke semua pengaturan konfigurasi "standar" terbaru, dll, terutama jika masalah alamat pengaturan konfigurasi baru tidak terjadi dalam pengujian RSpec. Cukup mudah untuk mengubah penyertaan yang dipicu metadata rspec-expectations untuk menggunakan config.include_context , bukan?

Kesimpulan awal: proyek Ruby populer yang menggunakan RSpec yang mengonfigurasi shared_context_metadata_behavior ke :apply_to_host_groups melakukan ini secara membabi buta dan tidak pernah menggunakannya.

Sejujurnya saya akan terkejut jika ada lebih dari segelintir pengguna yang telah memikirkan bagaimana tepatnya mereka ingin metadata grup contoh yang dibagikan untuk berperilaku, untuk kemudian pergi dan mengatur opsi konfigurasi ke perilaku yang mereka inginkan. Saya membayangkan hampir semua penggunaan :apply_to_host_groups dalam konfigurasi disebabkan oleh pembuatannya melalui rspec --init .

Saya tidak berpikir itu adalah argumen yang menentang :apply_to_host_groups , meskipun; seperti yang saya lihat, setengah dari manfaat :apply_to_host_groups adalah ia menonaktifkan perilaku penyertaan otomatis warisan implisit yang berlawanan dengan intuisi. Separuh manfaat lainnya adalah memungkinkan perilaku baru yang lebih sesuai (IMO, YMMV, tentu saja) dengan keseluruhan desain RSpec. Sebuah proyek yang mengonfigurasi :apply_to_host_groups dan kemudian tidak pernah benar-benar menandai grup bersama dengan metadata masih dapat mengambil manfaat dari opsi ini; masih ada perilaku yang berpotensi membingungkan yang mereka hindari. Misalnya, jika pengembang untuk sementara menandai grup bersama dengan :focus , bermaksud untuk memfokuskannya... ada baiknya RSpec tidak menyertakan grup bersama di grup lain yang menjadi :focus ed pada.

Tidak masuk akal untuk menerapkan metadata yang ditentukan untuk grup bersarang yang dibuat secara implisit.

Saya pikir :apply_to_host_groups masih memberikan perilaku yang bermanfaat untuk kasus ini, meskipun Anda benar bahwa menerapkan metadata ke grup Host tidak benar-benar berlaku di sini. Pertimbangkan kasus sekelompok contoh bersama yang semuanya bergantung pada database (dalam proyek yang menandai contoh tersebut dengan :db untuk membungkusnya dalam transaksi DB). Ini berguna bagi pengguna untuk dapat menandai grup contoh bersama mereka dengan :db untuk mengekspresikan ketergantungan pada database (dan untuk secara otomatis membungkus semua contoh yang ada dalam transaksi DB). Meskipun it_behaves_like tidak akan menggabungkan metadata :db ke dalam metadata grup host, masih bagus untuk dapat menandai grup bersama dengan :db dan menerapkannya ke contoh di dalamnya. Perilaku :trigger_inclusion warisan menghalangi kemungkinan ini karena ketika Anda melakukannya shared_examples_for "common metadata support", :db , tag :db digunakan untuk menyertakan otomatis grup bersama ini di :db -tagged kelompok.

Ini pada dasarnya adalah inti dari mengapa saya pikir :apply_to_host_groups lebih disukai: kami memiliki cara untuk menyertakan grup contoh bersama berdasarkan metadata menggunakan config.include_context (yang dengan baik mencerminkan config.include untuk modul. ..), tetapi jika kami secara implisit menggunakan metadata grup bersama untuk memicu penyertaan, ini mencegah pengguna untuk dapat menandai contoh bersama mereka dengan metadata umum di tingkat grup. Dan jika kami menggunakan metadata grup bersama dengan cara itu, maka IMO ekstensi alami itu untuk include_context / include_examples (ketika penyertaan tidak bersarang) adalah menggabungkan metadata dengan host metadata grup. (Tapi YMMV; itu hanya model mental saya tentang cara kerja metadata RSpec).

Namun, mengapa termasuk_konteks? Yah, kami hanya memiliki include_context pada objek Konfigurasi kami. Tidak ada include_examples atau it_behaves_like di sana.

Itu dengan desain. IMO, akan mengejutkan (dan aneh) untuk secara otomatis memasukkan beberapa contoh bersama di banyak grup contoh berdasarkan konteks. Seorang pengguna dapat melihat file spesifikasi, melihat 4 blok it (menyarankan menjalankan file akan menjalankan 4 contoh), menjalankannya, dan terkejut melihat 20 contoh dijalankan (misalnya karena 16 contoh bersama disertakan) . IMO, contoh adalah hal utama yang harus dilihat dan dipahami untuk memahami bagaimana rangkaian tes disusun, dan cara kerjanya. Kode harness pengujian bersama (misalnya metode helper, let s, atau hook around yang mengelola transaksi DB...) tidak memiliki kebutuhan yang sama untuk terlihat. Faktanya, saya cenderung menggunakan grup contoh bersama (dan include_context ) secara khusus untuk menyembunyikan detail yang tidak penting dari penambahan noise ke banyak spesifikasi. Misalnya, untuk masalah lintas sektoral seperti penangkapan log, atau transaksi DB, saya tidak ingin setiap pengujian yang memiliki masalah tersebut memiliki gangguan kode yang terlihat untuk mengelola hal-hal tersebut. Mampu menandai grup dengan :db atau :capture_logs dan membiarkan config.include_context menerapkan kode bersama untuk saya, menghasilkan spesifikasi dengan rasio signal-to-noise yang lebih tinggi. Ini tidak sama dengan include_examples / it_behaves_like , yang tidak dimaksudkan untuk digunakan untuk jenis masalah lintas sektoral yang sama yang bagus untuk ditangani secara otomatis.

Bagaimanapun, itu dua sen saya :). Karena saya tidak lagi terlibat dalam pemeliharaan RSpec, saya tidak merasa berkewajiban untuk memberikan pendapat saya secara berlebihan.

Semua 5 komentar

Saya ingin memanggil @myronmarston sebagai kekuatan pendorong di belakang :apply_to_host_groups .

Terima kasih telah menulis ini @pirj dan memanggil saya untuk berkomentar :).

Saya masih berpikir bahwa penyertaan implisit dari grup contoh bersama melalui metadata masih memiliki masalah. #1790 menguraikan masalah yang saya lihat dengannya ketika saya menulis masalah itu. Secara keseluruhan, perilaku inklusi implisit terasa tidak konsisten dengan RSpec lainnya, IMO; pertimbangkan bahwa semua cara lain yang memanfaatkan metadata RSpec, Anda mengonfigurasinya di blok RSpec.configure . Memiliki 1 fitur RSpec menggunakan metadata secara implisit (tanpa mengharuskan pengguna untuk mengonfigurasinya secara eksplisit dalam RSpec.configure ) adalah sesuatu yang saya harapkan akan membingungkan pengguna yang telah menggunakan metadata RSpec tetapi tidak mengetahui perilaku penyertaan implisit . Baik rspec-rails#1579 dan rspec-rails#1241 adalah contohnya: pengguna menandai grup contoh bersama mereka dengan metadata, mengharapkannya untuk bertindak seperti metadata pada tindakan grup normal (mis. memicu penyertaan config.include 'd modul, tersedia untuk pemfilteran, dll) dan terkejut melihat perilakunya tidak seperti itu. Faktanya, mereka sangat terkejut dengan hal itu sehingga mereka melaporkannya sebagai bug meskipun berfungsi seperti yang dirancang. Itu menunjukkan kepada saya bahwa itu adalah desain yang buruk untuk memulai: jika itu benar-benar selaras dengan RSpec lainnya, itu tidak akan mengarahkan pengguna untuk melaporkannya sebagai bug.

Sebagai kotak pasir untuk polisi rubocop-rspec baru, saya telah mengumpulkan daftar proyek Ruby yang paling banyak bintangnya yang menggunakan RSpec, rspec dunia nyata, ~ total 35 proyek. Dari 35 itu (termasuk repo RSpec juga!), 7 menggunakan :apply_to_host_groups di pembantu spesifikasi mereka:

Semantik yang tepat untuk menandai grup contoh bersama dengan metadata adalah sesuatu yang saya harapkan 99% dari pengguna RSpec tidak pernah memikirkan dan situasi membingungkan yang dipecahkan oleh perilaku yang lebih baru relatif jarang .... jadi saya tidak terkejut dengan itu sama sekali. TBH, saya menduga :apply_to_host_groups mungkin terutama digunakan oleh proyek yang menghasilkan (atau membuat ulang) spec_helper.rb setelah kami mengubah kode konfigurasi spec_helper.rb dihasilkan di 3589ab577d09db88ef5d5f0d60e8c35bfc55691f.

Untuk pengguna yang ingin memicu penyertaan grup contoh bersama berdasarkan metadata, disediakan API config.include_context yang, IMO, lebih sederhana, lebih konsisten, dan lebih eksplisit yang melakukannya secara otomatis untuk pengguna karena mereka menandai grup bersama dan grup normal dengan metadata yang sama. AFAIK, tidak ada yang disediakan :trigger_inclusion yang tidak dapat dicapai oleh pengguna yang menggunakan config.include_context secara eksplisit. (Jika ada sesuatu yang tidak dapat dicapai dengan cara itu, beri tahu saya!). OTOH, jika pengguna ingin menandai grup contoh bersama mereka dengan beberapa metadata, dan menerapkannya di mana pun grup bersama disertakan...Saya tidak berpikir ada mekanisme alternatif untuk ini. (Sebenarnya, mungkin config.define_derived_metadata dapat digunakan untuk mensimulasikan ini, tetapi IMO yang terasa seperti "menyelesaikan" untuk fitur yang kurang).

Secara pribadi, saya belum pernah melihat :apply_to_Host_groups digunakan seperti yang dirancang.

Inilah cara saya menggunakannya:

  • Saya telah menandai sementara grup contoh bersama dengan :focus , :pending , atau :skipped sehingga saya dapat fokus pada (atau memfilter) spesifikasi yang bergantung pada contoh bersama tertentu kelompok. Grup contoh bersama umumnya berarti ada beberapa masalah lintas sektoral yang berlaku untuk semua grup termasuk, dan dapat menjalankan hanya spesifikasi tersebut (atau mengecualikan spesifikasi tersebut) bisa sangat berguna. Perlu dicatat bahwa penggunaan fitur ini umumnya tidak akan muncul dalam kode yang dikomit untuk proyek apa pun, karena :focus , :skip dan :pending biasanya merupakan perubahan sementara yang tidak berkomitmen (terutama :focus ).
  • Ini bisa sangat berguna sebagai cara untuk mengekspresikan dependensi pada kode test harness lainnya. Misalnya, pertimbangkan sebuah proyek yang secara kondisional membungkus contoh dalam transaksi DB ketika mereka diberi tag :db . (Hal ini dapat dicapai dengan mendefinisikan DB support misalnya kelompok bersama dengan tepat around hook, dan kemudian menggunakan config.include_context "DB support", :db ). Sekarang bayangkan pengembang ingin mendefinisikan grup contoh bersama baru bernama logged in as admin yang mendefinisikan kait before yang membuat pengguna admin dalam database dan masuk sebagai pengguna tersebut menggunakan uji rak atau apa pun . Karena grup contoh bersama yang baru ini berinteraksi dengan database di hook before , ia memiliki ketergantungan pada grup contoh bersama DB support . IMO, cara terbersih untuk mengekspresikan ketergantungan ini adalah dengan menandai grup contoh bersama logged in as admin dengan :db sehingga dukungan DB diterapkan secara otomatis ketika logged in as an admin disertakan dalam grup host . Anda dapat melakukan include_context 'DB support' di grup contoh logged in as an admin untuk menerapkan transaksi DB secara otomatis, tetapi jika cara "normal" Anda mengelolanya di tempat lain adalah melalui tag :db itu aneh untuk tidak dapat melakukannya di sini.

Kami juga menggunakannya. rspec-harapan:

TERTAWA TERBAHAK-BAHAK :). Saya tidak terlalu terkejut dengan itu; kami belum secara historis memutakhirkan RSpec ke semua pengaturan konfigurasi "standar" terbaru, dll, terutama jika masalah alamat pengaturan konfigurasi baru tidak terjadi dalam pengujian RSpec. Cukup mudah untuk mengubah penyertaan yang dipicu metadata rspec-expectations untuk menggunakan config.include_context , bukan?

Kesimpulan awal: proyek Ruby populer yang menggunakan RSpec yang mengonfigurasi shared_context_metadata_behavior ke :apply_to_host_groups melakukan ini secara membabi buta dan tidak pernah menggunakannya.

Sejujurnya saya akan terkejut jika ada lebih dari segelintir pengguna yang telah memikirkan bagaimana tepatnya mereka ingin metadata grup contoh yang dibagikan untuk berperilaku, untuk kemudian pergi dan mengatur opsi konfigurasi ke perilaku yang mereka inginkan. Saya membayangkan hampir semua penggunaan :apply_to_host_groups dalam konfigurasi disebabkan oleh pembuatannya melalui rspec --init .

Saya tidak berpikir itu adalah argumen yang menentang :apply_to_host_groups , meskipun; seperti yang saya lihat, setengah dari manfaat :apply_to_host_groups adalah ia menonaktifkan perilaku penyertaan otomatis warisan implisit yang berlawanan dengan intuisi. Separuh manfaat lainnya adalah memungkinkan perilaku baru yang lebih sesuai (IMO, YMMV, tentu saja) dengan keseluruhan desain RSpec. Sebuah proyek yang mengonfigurasi :apply_to_host_groups dan kemudian tidak pernah benar-benar menandai grup bersama dengan metadata masih dapat mengambil manfaat dari opsi ini; masih ada perilaku yang berpotensi membingungkan yang mereka hindari. Misalnya, jika pengembang untuk sementara menandai grup bersama dengan :focus , bermaksud untuk memfokuskannya... ada baiknya RSpec tidak menyertakan grup bersama di grup lain yang menjadi :focus ed pada.

Tidak masuk akal untuk menerapkan metadata yang ditentukan untuk grup bersarang yang dibuat secara implisit.

Saya pikir :apply_to_host_groups masih memberikan perilaku yang bermanfaat untuk kasus ini, meskipun Anda benar bahwa menerapkan metadata ke grup Host tidak benar-benar berlaku di sini. Pertimbangkan kasus sekelompok contoh bersama yang semuanya bergantung pada database (dalam proyek yang menandai contoh tersebut dengan :db untuk membungkusnya dalam transaksi DB). Ini berguna bagi pengguna untuk dapat menandai grup contoh bersama mereka dengan :db untuk mengekspresikan ketergantungan pada database (dan untuk secara otomatis membungkus semua contoh yang ada dalam transaksi DB). Meskipun it_behaves_like tidak akan menggabungkan metadata :db ke dalam metadata grup host, masih bagus untuk dapat menandai grup bersama dengan :db dan menerapkannya ke contoh di dalamnya. Perilaku :trigger_inclusion warisan menghalangi kemungkinan ini karena ketika Anda melakukannya shared_examples_for "common metadata support", :db , tag :db digunakan untuk menyertakan otomatis grup bersama ini di :db -tagged kelompok.

Ini pada dasarnya adalah inti dari mengapa saya pikir :apply_to_host_groups lebih disukai: kami memiliki cara untuk menyertakan grup contoh bersama berdasarkan metadata menggunakan config.include_context (yang dengan baik mencerminkan config.include untuk modul. ..), tetapi jika kami secara implisit menggunakan metadata grup bersama untuk memicu penyertaan, ini mencegah pengguna untuk dapat menandai contoh bersama mereka dengan metadata umum di tingkat grup. Dan jika kami menggunakan metadata grup bersama dengan cara itu, maka IMO ekstensi alami itu untuk include_context / include_examples (ketika penyertaan tidak bersarang) adalah menggabungkan metadata dengan host metadata grup. (Tapi YMMV; itu hanya model mental saya tentang cara kerja metadata RSpec).

Namun, mengapa termasuk_konteks? Yah, kami hanya memiliki include_context pada objek Konfigurasi kami. Tidak ada include_examples atau it_behaves_like di sana.

Itu dengan desain. IMO, akan mengejutkan (dan aneh) untuk secara otomatis memasukkan beberapa contoh bersama di banyak grup contoh berdasarkan konteks. Seorang pengguna dapat melihat file spesifikasi, melihat 4 blok it (menyarankan menjalankan file akan menjalankan 4 contoh), menjalankannya, dan terkejut melihat 20 contoh dijalankan (misalnya karena 16 contoh bersama disertakan) . IMO, contoh adalah hal utama yang harus dilihat dan dipahami untuk memahami bagaimana rangkaian tes disusun, dan cara kerjanya. Kode harness pengujian bersama (misalnya metode helper, let s, atau hook around yang mengelola transaksi DB...) tidak memiliki kebutuhan yang sama untuk terlihat. Faktanya, saya cenderung menggunakan grup contoh bersama (dan include_context ) secara khusus untuk menyembunyikan detail yang tidak penting dari penambahan noise ke banyak spesifikasi. Misalnya, untuk masalah lintas sektoral seperti penangkapan log, atau transaksi DB, saya tidak ingin setiap pengujian yang memiliki masalah tersebut memiliki gangguan kode yang terlihat untuk mengelola hal-hal tersebut. Mampu menandai grup dengan :db atau :capture_logs dan membiarkan config.include_context menerapkan kode bersama untuk saya, menghasilkan spesifikasi dengan rasio signal-to-noise yang lebih tinggi. Ini tidak sama dengan include_examples / it_behaves_like , yang tidak dimaksudkan untuk digunakan untuk jenis masalah lintas sektoral yang sama yang bagus untuk ditangani secara otomatis.

Bagaimanapun, itu dua sen saya :). Karena saya tidak lagi terlibat dalam pemeliharaan RSpec, saya tidak merasa berkewajiban untuk memberikan pendapat saya secara berlebihan.

Terima kasih banyak atas jawaban yang mendetail dan berwawasan luas, @myronmarston!

bermanfaat bahwa RSpec tidak menyertakan grup bersama di grup lain yang sedang :focused aktif

Itu memang akan menjadi pendewaan kebingungan.

Keraguan saya hilang, saya akan melanjutkan dengan menjadikan :apply_to_host_groups sebagai opsi default dan satu-satunya.
Saya akan tetap membuka tiketnya, akan menghubungkan PR ke sana.

Keraguan saya hilang, saya akan melanjutkan dengan menjadikan :apply_to_host_groups sebagai opsi default dan satu-satunya.

Mungkin ada baiknya menghapus opsi konfigurasi sepenuhnya, mengingat rencananya adalah untuk tidak mendukung perilaku lain apa pun. Atau mungkin untuk kompatibilitas mundur itu dapat didefinisikan tetapi diabaikan (walaupun itu bisa membingungkan jika pengguna mengonfigurasi perilaku warisan ...). Saya tidak tahu apakah Anda berencana merilis RSpec 3.99 (seperti yang kami lakukan dengan 2.99) untuk memberikan peringatan pemutakhiran, tetapi jika Anda menggunakan rute itu 3.99 dapat mempertahankan opsi dan memperingatkan dengan tepat dan 4.0 tidak dapat memiliki opsi di semua mungkin.

Terima kasih atas jawaban terperinci @myronmarston :joy: Saya menutup ini karena saya setuju, dan menilai dari PR Phil dia juga yakin.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat