One-liner syntax in RSpec's should-based and expect-based syntaxes
RSpec supports a one-liner syntax for setting an expectation on the subject
:
describe Array do
describe "when first created" do
it { should be_empty }
end
end
The example description "it should be empty" will be defined automatically.
With RSpec 3's expect
-based syntax you use it_is_expected
instead:
describe Array do
describe "when first created" do
it { is_expected.to be_empty }
end
end
Testing ActiveRecord validations with RSpec
Validations should be covered by a model's spec.
This card shows how to test an individual validation. This is preferrable to save an entire record and see whether it is invalid.
Recipe for testing any validation
In general any validation test for an attribute :attribute_being_tested
looks like this:
- Make a model instance (named
record
below) - Run validations by saying
record.validate
- Check if
record.errors[:attribute_being_tested]
contains the expected validation error - Put the attribute into a valid state
- Run...
RSpec 3 argument constraints use weak equality
If you expect method calls in RSpec 3, be aware that the argument matchers use very liberal equality rules (more like ===
instead of ==
).
For example:
expect(subject).to receive(:foo).with(MyClass)
subject.foo(MyClass) # satisfies the expectation
subject.foo(MyClass.new) # also satisfies the expectation
expect(subject).to receive(:bar).with(/regex/)
subject.bar(/regex/) # satisfies the expectation
subject.bar('regex') # also satisfies the expectation
This is usually not an issue, except when your method ...
IIFEs in Coffeescript
In JavaScript we often use Immediately Invoked Function Expessions (or IIFEs) to prevent local variables from bleeding into an outside scope:
(function() {
var foo = "value"; // foo is scoped to this IIFE
})();
In Coffeescript an IIFE looks like this:
(->
foo = "value" # foo is scoped to this IIFE
)()
There is also a shorthand syntax with do
:
do ->
foo = "value" # foo is scoped to this IIFE
You can also use do
with arguments t...
RSpec: be_true does not actually check if a value is true
Don't use be_true
to check if a value is true
. It actually checks if it anything other than nil
or false
. That's why it has been renamed to be_truthy
in recent RSpec versions.
The same thing holds for be_false
, which actually checks if a value is not "truthy".
If you want to check for true
or false
in RSpec 2, write this instead:
value.should == true
value.should == false
If you want to check for true
or false
in RSpec 3+, write this instead:
e...
NoMethodError: undefined method `cache' for Gem:Module
I got this error when running Rails 2.3 tests for Rails LTS. More stacktrace:
NoMethodError: undefined method `cache' for Gem:Module
/vagrant/rails-2-3-lts-repository/railties/lib/rails_generator/lookup.rb:212:in `each'
/vagrant/rails-2-3-lts-repository/railties/lib/rails_generator/lookup.rb:146:in `to_a'
/vagrant/rails-2-3-lts-repository/railties/lib/rails_generator/lookup.rb:146:in `cache'
/opt/vagrant_ruby/lib/ruby/1.8/fileutils.rb:243:in `inject'
/vagrant/rails-2-3-lts-repository/railties/l...
Geordi 1.3 released
Changes:
- Geordi is now (partially) tested with Cucumber. Yay!
- geordi cucumber supports a new @solo tag. Scenarios tagged with
@solo
will be excluded from parallel runs, and run sequentially in a second run - Support for Capistrano 2 AND 3 (will deploy without
:migrations
on Capistrano 3) - Now requires a
.firefox-version
file to set up a test firefox. By default now uses the system Firefox/a test Chrome/whatever and doesn't print warnings any more. -
geordi deploy --no-migrations
(aliased-M
): Deploy with `cap ...
ActiveRecord meets database views with scenic
Using Scenic, you can bring the power of SQL views to your Rails application without having to switch your schema format to SQL. Scenic provides a convention for versioning views that keeps your migration history consistent and reversible and avoids having to duplicate SQL strings across migrations. As an added bonus, you define the structure of your view in a SQL file, meaning you get full SQL syntax highlighting in the editor of your choice and can easily test your SQL in the database console during development.
[https://robots.thoughtb...
Showing a custom maintenance page while deploying
Note
The maintenance mode is enabled on all application server as soon as the file
/public/system/maintenance.html
is present.
Installation
Add this line to your application's Gemfile:
gem 'capistrano', '~> 3.0'
gem 'capistrano-maintenance', '~> 1.0'
Add this line to you application's Capfile:
require 'capistrano/maintenance'
Enable task
Present a maintenance page to visitors. Disables your application's web interface by writing a #{maintenance_basename}.html
file to each web server. The servers m...
bash: print columns / a table
Ever wondered how you can create a simple table output in bash? You can use the tool column
for creating a simple table output.
Column gives you the possibility to indent text accurate to the same level. Pipe output to column -t
(maybe configure the delimeter with -s
) and see the magic happening.
detailed example
I needed to separate a list of databases and their corresponding size with a pipe symbol: |
Here is a example list.txt:
DB Size_in_MB
foobar 11011.2
barfoo 4582.9
donkey 4220.8
shoryuken 555.9
hadouken 220.0
k...
yujinakayama/transpec: The RSpec syntax converter
A comprehensive script to convert test suites from RSpec 2 to RSpec 3. This converts more than should/expect syntax.
How to render an html_safe string escaped
Once Rails knows a given string is html_safe
, it will never escape it. However, there may be times when you still need to escape it. Examples are some safe HTML that you pipe through JSON, or the display of an otherwise safe embed snippet.
There is no semantically nice way to do this, as even raw
and h
do not escape html_safe
strings (the former just marks its argument as html_safe
). You need to turn your string into an unsafe string to get the escaping love from Rails:
embed = javascript_tag('var foo = 1337;') # This is an h...
Geordi 1.2 released
Changes:
-
Remove some old binaries (commands still exist in
geordi
) and mark others as deprecated -
Rewrite deploy command to support most deploy scenarios:
- master to production
- feature branch to staging
- master to staging or production to production (plain deploy)
- Improve Cucumber command (fixes #18):
- Fix pass-through of unknown options to Cucumber
- Add --rerun=N option to rerun failed Cucumber tests up to N times. Reboots the test environment between runs, thus will pick up fixes you made durin...
How to open a new tab with Selenium
Until recently, you could open a new tab via window.open
when using execute_script
in Selenium tests. It no longer works in Chrome (will show a "popup blocked" notification).
This is because browsers usually block window.open
unless the user interacted with an element for security reasons. I am not sure why it did work via Selenium before.
Here is an approach that will insert a link into the page, and have Selenium click it:
path = "/your/path/here"
id = "helper_#{SecureRandom.hex(8)}"
execute_script <<-JAVASCRIPT
...
Using regular expressions in JavaScript
Regular expressions in Javascript are represented by a RegExp
object. There also is a regex literal as in many other languages: /regex/
. However, they are used slightly differently.
Regex literal
- Usage:
/foo+/
- Shorthand for creating a regular expression object
RegExp() object
- Usage:
RegExp("foo+")
ornew RegExp("foo+")
- No surrounding slashes required (they're the literal markers)
- Since the argument is a string, backslashes need to be escaped as well:
RegExp("\\d+")
Gotchas
- Regex objects [never eq...
RSpec & Devise: How to sign in users in request specs
You know that Devise offers RSpec test helpers for controller specs. However, in request specs, they will not work.
Here is a solution for request specs, adapted from the Devise wiki. We will simply use Warden's test helpers -- you probably already load them for your Cucumber tests.
First, we define sign_in
and sign_out
methods. These will behave just like ...
Defining and calling lambdas or procs (Ruby)
Ruby has the class Proc
which encapsulates a "block of code". There are 2 "flavors" of Procs
:
- Those with "block semantics", called
blocks
or confusingly sometimes alsoprocs
- Those with "method semantics", called
lambdas
lambdas
They behave like Ruby method definitions:
- They are strict about their arguments.
-
return
means "exit thelambda
"
How to define a lambda
-
With the
lambda
keywordtest = lambda do |arg| puts arg end
-
With the lambda literal
->
(since Ruby 1.9.1)
...
Stop writing "require 'spec_helper'" in every spec
Simply add this to your .rspec
instead:
--require spec_helper
If you are on rspec >= 3 and use a rails_helper.rb
require this instead of the spec_helper
:
--require rails_helper
If you are using parallel_tests
and this is not working for you, .rspec
might be ignored. Try using a .rspec_parallel
file.
Case Study: Analyzing Web Font Performance
Table of contents of the linked article:
What are Web Fonts?
- Advantages of Web Fonts
- Disadvantages of Web Fonts
- Fallback Fonts
- CSS3 @font Declaration Example
- Fallback Font Example
- Render Blocking and Critical Rendering Path
- FOIT
Optimizing Web Font Delivery Further
- Prioritize Based On Browser Support
- Choose Only Styles You Need
- Character Sets
- Host Fonts Locally or Prefetch
- Store in LocalStorage with Base64 Encoding
- Another Method
Web Font Pe...
Test your application's e-mail spam scoring with mail-tester.com
You can use mail-tester.com to check your application's e-mails for issues that might cause e-mails to be classified as spam.
They provide a one-time e-mail addresses that you can use to sign up etc. You can then check for scoring results of SpamAssassin and other potential issues.
You don't need to hit 10/10. Something around 9/10 is perfectly fine.
Note:
- For password-protected staging sites you will get an error for links that can not be resolved. This is fine, simply check production once available.
- ...
Lazy-loading images
Note
This card does not reflect the current state of lazy loading technologies. The native lazy attribute could be used, which is supported by all major browsers since 2022.
Since images are magnitudes larger in file size than text (HTML, CSS, Javascript) is, loading the images of a large web page takes a significant amount of the total load time. When your internet connection is good, this is usually not an issue. However, users with limited bandwidth (i.e. on mobile) need to mine their data budget...
How to run a small web server (one-liner)
Sometimes you just want to have a small web server that serves files to test something.
Serve the current directory
On Ruby 1.9.2+ you can do the following (".
" for current directory). You might need to gem install webrick
on modern Rubies.
ruby -run -ehttpd . -p8000
Python 2.x offers a similar way.
python -m SimpleHTTPServer 8000 .
This is the same way with Python 3.x
python -m http.server
In both cases your web server is single-threaded and will block when large files are being downloaded from you.
WEBrick ...
Gemspecs must not list the same gem as both runtime and development dependency
When you're developing a gem, never list the same dependency as both runtime and development dependency in your .gemspec
.
So don't do this:
spec.add_dependency 'activesupport'
spec.add_development_dependency 'activesupport', '~> 2.3'
If you do this, your gemspec will not validate and modern versions of Bundler will silently ignore it. This leads to errors like:
Could not find your-gem-0.1.2 in any of the sources
What to do instead
If you want to freeze a different version of a dependency for your t...
Reverse-proxying web applications with nginx
While you can use Apache as a reverse proxy, it tries to be too smart. Try nginx instead, it's much simpler to set up.
After struggling with Apache for quite a while, since I simply could not make it pass through the Digest Authentication of my target host (that I proxied to), I switched to nginx. Here is what I did.
-
Have nginx
sudo apt-get install nginx
-
Define your nginx config, e.g. at
/etc/nginx/conf.d/reverse-proxy.conf
:server { listen 127.0.0.1; location /...