You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: sites/en/testing/additional_concepts.step
+13-11Lines changed: 13 additions & 11 deletions
Original file line number
Diff line number
Diff line change
@@ -4,28 +4,28 @@ message <<-MARKDOWN
4
4
### Doubles and stubs
5
5
Doubles are simpler objects that represent objects from your application.
6
6
<div class="console"><pre>
7
-
post = double(:post)
7
+
orange = double(:orange)
8
8
</pre>
9
9
</div>
10
-
If you instantiate that double in your test file, you have access to post in your tests to test with. This is instead of creating an entire Post 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.
10
+
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.
11
11
12
12
Stubs can be used to dictate what is returned when a method is called on a double.
13
13
<div class="console"><pre>
14
-
post.stub(:title).and_return("Jelly")
14
+
orange.stub(:name).and_return("Florida Orange")
15
15
</pre>
16
16
</div>
17
-
So, when you write a test that calls the title attribute of the post double, you'll always get back the string Jelly. Got it? Good!
17
+
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!
18
18
19
19
### Spies
20
20
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.
21
-
For instance (assume you already have the post double from above):
21
+
For instance (assume you already have the orange double from above):
22
22
<div class="console"><pre>
23
-
post = spy('post')
24
-
post.content
25
-
expect(post).to have_received(:content)
23
+
orange = spy('orange')
24
+
orange.name
25
+
expect(orange).to have_received(:name)
26
26
</pre>
27
27
</div>
28
-
Obviously, this is a simplified case. Instead of post.content, 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!
28
+
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!
29
29
30
30
### Webmock
31
31
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!
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.
40
+
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.
41
41
MARKDOWN
42
42
43
43
console_without_message <<-RUBY
@@ -53,5 +53,7 @@ RUBY
53
53
message <<-MARKDOWN
54
54
So, if you write any tests in your test files that call the Bitly API, then the response will be whatever you defined above. The test will prevent the actual API request from being made. Pretty cool, huh?
55
55
56
-
Awesome, you are now equipped with a license to TEST! Go forth and create doubles, stubs, and spies in your app (at least one of each and have a TA verify).
56
+
Awesome, you are now equipped with a license to TEST! Go forth and create doubles, stubs, and spies in your app (at least one of each and have a TA verify). And, if you have time for a final challenge (optional), click below...
Congratulations! Take a second and give yourself a pat on your back. You've come far, my young padawan. This is the final test (no pun intended haha!) :)
4
+
5
+
# The final challenge
6
+
Essentially, you will clone a repo (link is below) that has broken tests and fix all the broken tests. The broken tests will consist of a variety of different types of tests, incorporating everything you have learned thus far. Good luck, keep calm, and test on!
Copy file name to clipboardExpand all lines: sites/en/testing/testing_frameworks.step
+8-8Lines changed: 8 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -1,16 +1,16 @@
1
1
message <<-MARKDOWN
2
2
# What's a testing framework?
3
-
A testing framework is an execution environment for automated tests. Think of it as the set of assumptions that reminds you when you veer away from those assumptions. In short Test frameworks helps teams organize their test suites and in turn
4
-
help improve the efficiency of testing.
3
+
A testing framework is an execution environment for automated tests. Testing frameworks help teams organize their test suites and in turn
4
+
help improve the efficiency of testing.
5
5
6
6
# 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. Mini Test is the default testing framework in Rails 5. However, we will be using the RSpec testing framework instead.
8
8
9
9
10
10
# RSpec
11
11
## How to set up RSpec in Rails
12
12
13
-
Add rspec-rails to both the :development and :test groups in the Gemfile:
13
+
First, create a new Rails app. Then, add rspec-rails to both the :development and :test groups in the Gemfile:
14
14
15
15
<div class="console"><pre>
16
16
group :development, :test do
@@ -48,7 +48,7 @@ bundle exec rspec
48
48
</pre>
49
49
</div>
50
50
51
-
By default the above will run all spec files in the spec directory.
51
+
By default, the above code will run all spec files in the spec directory.
52
52
53
53
To run only a subset of these specs use the following command:
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.
95
+
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.
Copy file name to clipboardExpand all lines: sites/en/testing/types_of_tests.step
+29-27Lines changed: 29 additions & 27 deletions
Original file line number
Diff line number
Diff line change
@@ -3,62 +3,64 @@ message <<-MARKDOWN
3
3
4
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.
5
5
6
-
Take a look at the following Post model in your app:
6
+
Create the Orange and Tree models in your app so that the model files are something like this:
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 post should have certain associations and validations. Let's start by writing some model tests also known as unit tests!
21
+
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!
18
22
MARKDOWN
19
23
20
24
steps do
21
25
step do
22
-
message "First, create a post model spec file in the models folder of the spec folder. Type this in the terminal:"
26
+
message "First, create a orange model spec file in the models folder of the spec folder. Type this in the terminal:"
23
27
24
28
console_without_message "cd app/spec/models"
25
-
console_without_message "touch post_spec.rb"
29
+
console_without_message "touch orange_spec.rb"
26
30
end
27
31
step do
28
32
message "Then, run rspec."
29
33
30
34
console_without_message "bundle exec rpsec"
31
35
32
-
message "You should see some report but no tests exist yet. So, let's add one! Copy the below test, paste it into the post model spec file and then run 'bundle exec rspec' on the terminal again."
36
+
message "You should see some report but no tests exist yet. So, let's add one! Copy the below test, paste it into the orange model spec file and then run 'bundle exec rspec' on the terminal again."
33
37
34
38
console_without_message <<-RUBY
35
39
describe 'ActiveRecord associations' do
36
-
it 'Post belongs to users' do
37
-
expect(Post.reflect_on_association(:user).macro).to be (:belongs_to)
40
+
it 'Orange belongs to tree' do
41
+
expect(Orange.reflect_on_association(:tree).macro).to be (:belongs_to)
38
42
end
39
43
end
40
44
RUBY
41
45
42
-
message "Great, now you should see one passing test! That's an example of an association test. Let's modify that test to fail. Then, run 'bundle exec rspec' and see what happens. Cool! Let's revert back to the passing test. And, write another association test for the relationship between the Post model and the Reply model!"
46
+
message "Great, now you should see one passing test! That's an example of an association test. Let's modify that test to fail. Then, run 'bundle exec rspec' and see what happens. Cool! Let's revert back to the passing test. And, write a has many association test for the relationship between the Tree model and the Orange model!"
43
47
44
48
end
45
49
end
46
50
47
51
48
52
message <<-MARKDOWN
49
-
On to controller tests! Just like the Post model, assume we have the following controller in our app (the other methods are omitted for brevity):
53
+
On to controller tests! Just like the Orange model, create the following controller in your app (the other methods are omitted for brevity):
50
54
51
55
<div class="console"><pre>
52
-
class PostsController < ApplicationController
53
-
include PostsHelper
54
-
56
+
class OrangesController < ApplicationController
55
57
def index
56
-
@posts = Post.all
58
+
@oranges = Orange.all
57
59
render :index
58
60
end
59
61
60
62
def new
61
-
@post = Post.new
63
+
@orange = Orange.new
62
64
render :new
63
65
end
64
66
end
@@ -68,17 +70,17 @@ MARKDOWN
68
70
69
71
steps do
70
72
step do
71
-
message "First, create a posts controller spec file in the controllers folder of the spec folder. Type this in the terminal:"
73
+
message "First, create an orange controller spec file in the controllers folder of the spec folder. Type this in the terminal:"
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 posts controller spec file and then run 'bundle exec rspec' on the terminal again."
83
+
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 and then run 'bundle exec rspec' on the terminal again."
82
84
83
85
console_without_message <<-RUBY
84
86
describe '#index' do
@@ -100,26 +102,26 @@ steps do
100
102
end
101
103
102
104
message <<-MARKDOWN
103
-
Last but not least: view tests! Below is an short snippet of the Post show HTML page in your app:
105
+
Last but not least: view tests! Below is an short snippet of a possible Orange show HTML page you can create in your app:
104
106
MARKDOWN
105
107
console_without_message <<-HTML
106
108
<br>
107
-
Post title: <%= @post.title %>
109
+
Orange title: <%= @orange.name %>
108
110
<br>
109
111
<br>
110
-
Post content: <%= @post.content %>
112
+
Orange tree id: <%= @orange.tree_id %>
111
113
<br>
112
114
HTML
113
115
114
116
message <<-MARKDOWN
115
-
So, based on the post you create, the show page should render HTML with the post's title and content. Let's verify that with a few tests.
117
+
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.
116
118
MARKDOWN
117
119
118
120
steps do
119
121
step do
120
-
message "First, create a posts view spec file in the views folder of the spec folder. Type this in the terminal:"
122
+
message "First, create an oranges view spec file in the views folder of the spec folder. Type this in the terminal:"
Copy file name to clipboardExpand all lines: sites/en/testing/what_are_tests.step
+9-9Lines changed: 9 additions & 9 deletions
Original file line number
Diff line number
Diff line change
@@ -1,21 +1,21 @@
1
1
message <<-MARKDOWN
2
-
Tests are ways of testing our code to see if they are performing the way we have intended it behave.
2
+
3
+
Tests are not exams like the ones you have to take in school. Rather, tests are ways of testing code to see if it is performing the way we expect it to behave. Pretty easy, right?
3
4
4
5
# Example
5
-
For example, lets say we wanted to create a program that models an orange tree. Well, what defines an orange tree to us? Is it safe to say that we need at least two objects, an orange object and a tree object? Can our tree mature and bear more fruit at a certain age? Could our oranges ripen and fall from the tree? Sounds like the list can become lengthy right? Lets stop here for a few minutes and see what we need to fulfill these user stories.
6
+
For example, let's say we wanted to create a program that models an orange tree because nature is awesome. Well, what defines an orange tree to us? Is it safe to say that we need at least two objects, an orange object and a tree object? Can our tree mature and bear more fruit at a certain age? Could our oranges ripen and fall from the tree? Sounds like the list can become lengthy, right? Let's stop here for a few minutes and see what we need to fulfill these user stories.
6
7
7
8
# What We Need To Test?
8
-
Remember that we need to model an orange and a tree, so we know that there are two objects that needs to be created.
9
+
Remember that we need to model an orange and a tree. So, we know that there are two objects that need to be created.
9
10
10
-
We could say that the tree will not bear fruit until it matures at one year of age and then it well bare an X amount of oranges. We would need a test to test if the tree ages and a test to see if the tree has created an X amount of oranges once it has matured.
11
-
12
-
How do we determine if an orange is ripe? Well, we can have oranges age and if it is at least 30 days old, then it will fall from the tree. We would need to write a test to check for ripeness and a test to check if it falls at ripeness.
11
+
We could say that the tree will not bear fruit until it matures at one year of age and then it will bear X number of oranges. We would need a test to test if the tree ages and a test to see if the tree has created X number of oranges once it has matured.
13
12
14
-
# Now That We Have Tests
15
-
You could think of tests as a requirement list. Every time a change is made we want to test to see if our code still meets those requirements. For example, as our program becomes increasingly complex and we want to have our tree to have a certain lifespan, would it make sense for our tree to continue to create oranges after exceeding that lifespan?
13
+
How do we determine if an orange is ripe? Well, we can have an orange age and if it is at least 30 days old, then it will fall from the tree. We would need to write a test to check for ripeness and a test to check if it falls at ripeness.
16
14
17
15
# Why Is It Important That We Test?
18
-
For situations like our tree's lifespan is a prime example of why tests are important. As our program becomes more complex over time the tests tells us that a basic requirement is not fulfilled and needs to be addressed. Can you imagine looking at pages and pages of code that was written by someone else or many years ago without a way to trace exactly where the bug is? Tests can help!
16
+
You could think of tests as a requirement list. Every time a change is made we want to test to see if our code still meets those requirements. For example, as our program becomes increasingly complex and we want to have our tree to have a certain lifespan, would it make sense for our tree to continue to create oranges after exceeding that lifespan?
17
+
18
+
A situation like our tree's lifespan is a prime example of why tests are important. As our program becomes more complex over time with new code added, the tests tell us that the new code negatively affected prior expectations of the behavior of the code. Tests can help keep the original behavior of the code and prevent new bugs from appearing.
19
19
20
20
# Test Driven Development
21
21
Test-driven development (TDD) is a development technique where you must first write a test that fails before you write new functional code. TDD is a great way to develop your program! Add a test, run all tests, write code, run tests, and then refactor code!
0 commit comments