Here are a few common patterns that will probably lead to flaky specs. If you notice them in your specs, please make sure that you have not introduced a flaky...
Using Capybara RSpec matchers One rule of thumb I try to follow in capybara tests is using capybara matchers and not plain rspec matchers. One example: visit(some_page...
...block evaluates to true. first_post_with_image = posts.find do |post| post.image end However, sometimes it's not the item you're interested in, but some value depening on it...
...image).find(&:present?).url If the mapping is a costly operation or has undesirable side effects, you need to do it in a single iteration instead. Single iteration solution with...
...can use ETags to allow clients to use cached responses, if your application would send the same contents as before. Besides what "actually" defines your response's contents, your application...
...probably also considers "global" conditions, like which user is signed in: class ApplicationController < ActionController::Base etag { current_user&.id } etag { current_user&.updated_at } end Under the hood, Rails generates...
...record/replay cassettes for any RSpec example tagged as :vcr or vcr: true. If a spec is not tagged with :vcr, VCR will complain about any attempted HTTP request. This is...
...this off temporarily, e.g. to communicate with an actual API while writing a new spec, simply add the line c.allow_http_connections_when_no_cassette = true to the VCR.configure-block...
...with a nice way to grep through your project's files: The finder (ctrl + shift + f). Don't be discouraged about the notice 100+ matches in n+ files if your...
...searched keyword is too general or widely used in your project. RubyMine comes with a few ways to narrow down the resulting list, don't hesitate to apply those filters...
Debouncing a method call delays its execution until after a specified time has passed. If it's called again before that time has passed, its execution is delayed again.
...would be run more often than it needs to. One example for that are scroll event handlers in JavaScript: You want to react to a user scrolling, but it's...
Applications often show or hide elements based on viewport dimensions, or may have components that behave differently (like mobile vs desktop navigation menus). Since you want your integration tests to...
...behave consistently, you want to set a specific size for your tests' browser windows. Using WebDriver options / Chrome device metrics For Google Chrome, the preferred way is setting "device metrics...
...for file uploads. CarrierWave has an integrated processing mechanism for different file versions with support for ImageMagick through CarrierWave::MiniMagick (which requires the mini_magick gem). In case your processing...
...runs into an error, CarrierWave will just swallow it and rethrow an error with a very generic message like Processing failed. Maybe it is not an image? which does not...
GoodJob and ActiveJob rescue exceptions internally, preventing exception_notification from triggering. This can cause silent job failures.To get notified, subscribe to ActiveJob events and configure GoodJob's on_thread_error...
...job failures, as they are handled internally by ActiveJob/GoodJob. ActiveSupport::Notifications.subscribe(/(enqueue_retry|retry_stopped|discard)\.active_job/) do |event_name, *, payload| exception = payload[:error] job = payload[:job]
Modern CSS offers the field-sizing property to allow elements to automatically adjust size (width and/or height) to fit their contents. The most common use case are textareas which start...
...fairly small (e.g. 2 or 3 rows tall) but grow when users enter longer text. Usage textarea { field-sizing: content; } That's it! At least in modern Chromium-based browsers...
...updates all your gems at once. Given that many gems don't care about stable APIs, this might break your application in a million ways. To stay sane, update your...
...This ensures that your libraries are up-to-date while it's easy to spot major version bumps which may break the app. Projects that have not been updated in...
...bug) and want to use git bisect to find out when it was introduced? Smart kid. If you have a shell command ready to reveal if your current state is...
...other hand will use the return value of that call to decide if the state is good or bad. First, start bisecting git bisect start Then tell git which revisions...
...the commit which was deployed. If you want to know the currently deployed release, simply SSH to a server and view that file. $ cat /var/www/my-project/current/REVISION cf8734ece3938fc67262ad5e0d4336f820689307 Capistrano task
...application is deployed to multiple servers, you probably want to see a result for all of them. Here is a Capistrano task that checks all servers with the :app role...
Geordi provides a pretty neat way to generate beautiful commit messages according to your stories in Linear: geordi commit Geordi reads from a .geordi.yml file inside your repo and connects...
...to Linear to list started and finished stories with their title. Choosing one of them generates a commit message including id and title from Linear app and a link to...
Capybara-screenshot can automatically save screenshots and the HTML for failed Capybara tests in Cucumber, RSpec or Minitest. Requires Capybara-Webkit, Selenium or poltergeist for making screenshots. Screenshots are saved...
...into $APPLICATION_ROOT/tmp/capybara. Manually saving a page Additionally you can trigger the same behavior manually from the test using Capybara::Session#save_and_open_page and Capybara::Session#save_screenshot...
Because your examples should not change global state, you should not need to care about the order in which RSpec processes your .rb files. However, in some cases you might...
...rb files in alphabetical order of their file paths by default (or when you specify --order defined). You run tests in random order by using --order random on the command...
...with two matchers that test for equality. The first is toBe: expect(first).toBe(second) toBe passes when first === second. Unfortunately this is useless for non-primitive values because JavaScript...
...is a horrible language. However, Jasmine comes with another matcher toEqual: expect(first).toEqual(second) This matcher behaves as a human would expect for types like the following: Arrays
Sometimes you need to remove high Unicode characters from a string, so all characters have a code point between 0 and 127. The remaining 7-bit-encoded characters ("Low-ASCII...
...can be transported in most strings where escaping is impossible or would be visually jarrring. Note Transliteration this will change the string. If you need to preserve the exact string...
This card is a short summary on different ways of assigning multiple attributes to an instance of a class. Using positional parameters Using parameters is the default when assigning attributes...
...It works good for a small number of attributes, but becomes more difficult to read when using multiple attributes. Example: class User def initialize(salutation, first_name, last_name, street...
...pretty_print method As an example, consider the following class. class MyClass # ... def inspect "#<#{self.class} attr1: #{attr1.inspect}, attr2: #{attr2.inspect}>" end end Instances of that class will inspect like #<MyClass attr1...
...Alice", attr2: "Bob">, but IRB will apply a single color (green) for everything. That is because MyClass implements only inspect. If it were to implement pretty_print, IRB would use...
...want to be in there. In order to reduce the chance to accidentally commit something you didn't intend, review your changes before committing. My preferred way of doing this...
...paths (including new files), but not their contents git add -p Git will now show you all your changes in small chunks and ask you in an interactive mode whether...
...or ::1 (IPv6) can only be reached from your own PC: Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process tcp LISTEN...
...address 0.0.0.0 can be reached from other PCs on your network: Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process tcp LISTEN...
...notice that the records you create are not deleted and will bleed into your specs the next time you run them. You probably have DatabaseCleaner configured to take care of...
...not bloating your test database with old records: RSpec.configure do |config| config.before(:suite) do DatabaseCleaner.clean_with(:deletion) end config.before(:each) do DatabaseCleaner.strategy = :transaction end config.before(:each, transaction: false) do DatabaseCleaner.strategy...
...files. Those can be used to apply to a different repository [1] or by someone else (e.g. sent when sent to them via e-mail). Creating a patch in git...
...changes and commit them. Run git format-patch COMMIT_REFERENCE to convert all commits since the referenced commit (not including it) into patch files. For example, let's say you...