Skip to content

Commit 492d7f2

Browse files
committed
Edits to rails testing curriculum
* minitest is styled `minitest` or maybe `Minitest`, but not `Mini Test` * Fix a lingering `Rspec.describe` -> `RSpec.describe` * Show ruby source code with ruby syntax highlighting * Fix some content in types_of_test page that was outside of a 'step'
1 parent b04d78b commit 492d7f2

File tree

3 files changed

+78
-79
lines changed

3 files changed

+78
-79
lines changed

sites/en/testing/additional_concepts.step

+23-19
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,55 @@ message <<-MARKDOWN
33

44
### Doubles and stubs
55
Doubles are simpler objects that represent objects from your application.
6-
<div class="console"><pre>
6+
7+
```ruby
78
orange = double(:orange)
8-
</pre>
9-
</div>
9+
```
10+
1011
If you instantiate that double in your test file, you have access to orange in your tests to test with. This is instead of creating an entire Orange model in ActiveRecord. If you need to create many different test objects with different properties, FactoryGirl is a great gem for that purpose and will allow persistence or in-memory object creation, depending on your testing situation.
1112

1213
Stubs can be used to dictate what is returned when a method is called on a double.
13-
<div class="console"><pre>
14+
15+
```ruby
1416
orange.stub(:name).and_return("Florida Orange")
15-
</pre>
16-
</div>
17+
```
18+
1719
So, when you write a test that calls the title attribute of the orange double, you'll always get back the string Florida Orange. Got it? Good!
1820

1921
### Spies
2022
With spies, we are not talking about espionage... at least, not in relation to testing :) Spies can be used to verify whether a method was called on an object.
2123
For instance (assume you already have the orange double from above):
22-
<div class="console"><pre>
24+
25+
```ruby
2326
orange = spy('orange')
2427
orange.name
2528
expect(orange).to have_received(:name)
26-
</pre>
27-
</div>
29+
```
30+
2831
Obviously, this is a simplified case. Instead of orange.name, you might have a complicated method that executes many functions internally and that's where spies can come in handy; they can check easily whether one specific method was called. Capiche? Ok, let's keep on trucking!
2932

3033
### Webmock
3134
What if your app relies on third-party services or applications, known amongst friends as application programming interfaces or APIs? Well, it seems like APIs should also be tested but should our test suite really be dependent on someone else? NOPE! What if the API goes down? Or is slow? Welcome to the stage: Webmock!
3235
Webmock is a gem that stubs out external HTTP requests. Once you include the gem, bundle install, and include the below code snippet in your spec helper file (which is included in every test file), you're good to go.
3336
MARKDOWN
34-
console_without_message <<-RUBY
35-
require 'webmock/rspec'
36-
WebMock.disable_net_connect!(allow_localhost: true)
37+
38+
source_code :ruby, <<-RUBY
39+
require 'webmock/rspec'
40+
WebMock.disable_net_connect!(allow_localhost: true)
3741
RUBY
3842

3943
message <<-MARKDOWN
4044
Then, you can start stubbing out API requests in your spec helper file. Let's write an example for Bitly, a service that shortens long URLs. This may come in handy when you want to provide external links to info pages about the different types of oranges in your orange tree but the links are too long to display on a line.
4145
MARKDOWN
4246

43-
console_without_message <<-RUBY
44-
RSpec.configure do |config|
45-
config.before(:each) do
46-
stub_request(:get, /api.bitly.com.v3.shorten/).
47-
with(headers: {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}).
48-
to_return(status: 200, body: "stubbed response", headers: {})
47+
source_code :ruby, <<-RUBY
48+
RSpec.configure do |config|
49+
config.before(:each) do
50+
stub_request(:get, /api.bitly.com.v3.shorten/).
51+
with(headers: {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}).
52+
to_return(status: 200, body: "stubbed response", headers: {})
53+
end
4954
end
50-
end
5155
RUBY
5256

5357
message <<-MARKDOWN

sites/en/testing/testing_frameworks.step

+18-22
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ A testing framework is an execution environment for automated tests. Testing fra
44
help improve the efficiency of testing.
55

66
# Types of testing frameworks
7-
There are many testing frameworks that work great. Mini Test is the default testing framework in Rails 5. However, we will be using the RSpec testing framework instead.
7+
There are many testing frameworks that work great. Minitest is the default testing framework in Rails 5. However, we will be using the RSpec testing framework instead.
88

99

1010
# RSpec
@@ -19,11 +19,11 @@ rails new testapp
1919

2020
Then, add rspec-rails to both the :development and :test groups in the Gemfile:
2121

22-
<div class="console"><pre>
22+
```ruby
2323
group :development, :test do
2424
gem 'rspec-rails', '~> 3.4'
25-
end</pre>
26-
</div>
25+
end
26+
```
2727

2828
Download and install by running:
2929

@@ -70,18 +70,17 @@ bundle exec rspec spec/controllers/post_controller_spec.rb
7070

7171
## RSpec Basics
7272

73-
<div class="console"><pre>
74-
1 Rspec.describe Tree do
75-
2 it "is able to age by 1 year increments" do
76-
3 orange_tree = Tree.new
77-
4 orange_tree.age
78-
5 expect(orange_tree.age).to eq(1)
79-
6 end
80-
7 end
81-
</pre>
82-
</div>
73+
```ruby
74+
RSpec.describe Tree do
75+
it "is able to age by 1 year increments" do
76+
orange_tree = Tree.new
77+
orange_tree.age
78+
expect(orange_tree.age).to eq(1)
79+
end
80+
end
81+
```
8382

84-
The 'describe' and 'it' methods come from rspec-core. The Tree class would be from your code. You can think of 'describe' as a header to describe which class you are testing and 'it' as a string/subheader that states what specifically you are testing in the Tree class. Note: you may or may not need the Rspec in front of the describe depending on your Rspec version.
83+
The 'describe' and 'it' methods come from rspec-core. The Tree class would be from your code. You can think of 'describe' as a header to describe which class you are testing and 'it' as a string/subheader that states what specifically you are testing in the Tree class. Note: you may or may not need the RSpec in front of the describe depending on your RSpec version.
8584

8685
The last line of the example expresses an expected outcome. If orange_tree.age == 1, then the example passes. If not, it fails with a message like:
8786

@@ -98,13 +97,11 @@ Remember in our example on line 5? 'to eq' is a matcher. RSpec has many built-in
9897
Check out the other built-in matchers!
9998
https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers
10099

101-
# Mini Test
102-
In case you were curious to see how tests are written in Mini Test. Mini Test also allows you to write tests in 'expectation style' which is very similar to how RSpec tests are written.
100+
# minitest
101+
In case you were curious to see how tests are written in minitest. Minitest also allows you to write tests in 'expectation style' which is very similar to how RSpec tests are written.
103102

104-
<div class="console">
105-
<pre>
103+
```ruby
106104
class TestTree < Minitest::Test
107-
108105
def setup
109106
@orange_tree = Tree.new
110107
@orange_tree.age
@@ -114,8 +111,7 @@ class TestTree < Minitest::Test
114111
assert_equal 1, @orange_tree.age
115112
end
116113
end
117-
</pre>
118-
</div>
114+
```
119115

120116
To run the test enter the following in Terminal/Command Prompt:
121117

sites/en/testing/types_of_tests.step

+37-38
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
message <<-MARKDOWN
22
Now, that you know what tests are, let's discuss the different types of tests!
33

4-
In your Rails app, you have models, views, and controllers -> is MVC ringing a bell? :) Well, it should be no surprise that tests can be written for models, views, and controllers.
4+
In your Rails app, you have models, views, and controllers. It should be no surprise that tests can be written for models, views, and controllers.
55

66
As you learned in the previous section, tests are used to verify that your code is working as expected. So, a couple things we can test right off the bat are that a tree should have certain associations and validations. Let's start by writing some model tests also known as unit tests! This link might come in handy to remember singular vs. plural Rails conventions: https://alexander-clark.com/blog/rails-conventions-singular-or-plural/
77
MARKDOWN
@@ -24,19 +24,19 @@ steps do
2424
message "You will see a report with one pending test. When you generated your Orange model, RSpec also generated a matching spec file. Copy the test below into spec/models/orange_spec.rb and run 'bundle exec rspec' on the terminal again."
2525

2626

27-
console_without_message <<-RUBY
28-
RSpec.describe Orange, :type => :model do
29-
context 'ActiveRecord associations' do
30-
it 'Orange belongs to tree' do
31-
expect(Orange.reflect_on_association(:tree).macro).to be (:belongs_to)
27+
source_code :ruby, <<-RUBY
28+
RSpec.describe Orange, :type => :model do
29+
context 'ActiveRecord associations' do
30+
it 'Orange belongs to tree' do
31+
expect(Orange.reflect_on_association(:tree).macro).to be (:belongs_to)
32+
end
3233
end
3334
end
34-
end
3535
RUBY
3636

3737
message "Run 'bundle exec rspec'. This test fails! Let's add an associaton to our model. Add a belongs_to association to orange.rb:"
3838

39-
console_without_message <<-RUBY
39+
source_code :ruby, <<-RUBY
4040
class Orange < ActiveRecord::Base
4141
belongs_to :tree
4242
end
@@ -66,20 +66,20 @@ steps do
6666

6767
message "You should see a report with some passing tests but those are just the model tests you wrote. So, let's add some controller tests! Copy the below test, paste it into the oranges controller spec file, create the relevant view files and then run 'bundle exec rspec' on the terminal again."
6868

69-
console_without_message <<-RUBY
70-
RSpec.describe OrangesController do
71-
context '#index' do
72-
it "renders the index view" do
73-
get :index
74-
expect(response).to render_template("index")
75-
end
76-
77-
it "renders html" do
78-
process :index, method: :get
79-
expect(response.content_type).to eq "text/html"
69+
source_code :ruby, <<-RUBY
70+
RSpec.describe OrangesController do
71+
context '#index' do
72+
it "renders the index view" do
73+
get :index
74+
expect(response).to render_template("index")
75+
end
76+
77+
it "renders html" do
78+
process :index, method: :get
79+
expect(response.content_type).to eq "text/html"
80+
end
8081
end
8182
end
82-
end
8383
RUBY
8484

8585
message "You should see two failing tests. You'll need to add a route, index action, and a view. Not sure where to start? Read the errors in your failing tests for a hint. Run 'bundle exec rspec' after each change until both tests pass."
@@ -90,26 +90,25 @@ steps do
9090
step do
9191
message "Now, write another controller test for the new action (hint: you might need to look up what a mock is)."
9292
end
93-
end
9493

95-
message <<-MARKDOWN
96-
Last but not least: view tests! Below is an short snippet of a possible Orange show HTML page you can create in your app:
97-
MARKDOWN
98-
console_without_message <<-HTML
99-
<br>
100-
Orange title: <%= @orange.name %>
101-
<br>
102-
<br>
103-
Orange tree id: <%= @orange.tree_id %>
104-
<br>
105-
HTML
106-
107-
message <<-MARKDOWN
108-
So, based on the orange you create, the show page should render HTML with the orange's name and tree id. Let's verify that with a few tests.
109-
MARKDOWN
110-
111-
steps do
11294
step do
95+
message <<-MARKDOWN
96+
Last but not least: view tests! Below is an short snippet of a possible Orange show HTML page you can create in your app:
97+
MARKDOWN
98+
99+
source_code :erb, <<-ERB
100+
<br>
101+
Orange title: <%= @orange.name %>
102+
<br>
103+
<br>
104+
Orange tree id: <%= @orange.tree_id %>
105+
<br>
106+
ERB
107+
108+
message <<-MARKDOWN
109+
So, based on the orange you create, the show page should render HTML with the orange's name and tree id. Let's verify that with a few tests.
110+
MARKDOWN
111+
113112
message "First, create a views folder in the spec folder. Then, create an oranges folder in the views folder. Lastly, create an oranges view spec file in the oranges folder. Type these commands in the terminal:"
114113

115114
console_without_message "mkdir app/spec/views"

0 commit comments

Comments
 (0)