-
Notifications
You must be signed in to change notification settings - Fork 168
Test Driven Development Lessons #114
Comments
Introduction to RSpec lesson done by @leosoaivan IntroductionIn the previous lesson, we established the utility of test-driven development (TDD) in maintaining your code and sanity. In this lesson, we'll introduce you to your new best friend, the RSpec testing framework. RSpec is one of the most popular testing frameworks, having been downloaded over 100 million times and having been ported for use in Rails development. Learning OutcomesLook through these now and use them to guide your learning. By the end of this lesson, expect to:
Introduction to RSpecWhat is RSpec, and why RSpec?At the most basic level, RSpec is a Domain Specific Language written in Ruby, or, for the rest of us, a language specialized for a particular task. In this case, the task is testing Ruby code. The At this point, you may be wondering, Why RSpec? Surely, there are other frameworks out there, and you'd be right. There are. In fact, at one point, Ruby came bundled with Test::Unit and later Minitest as part of its standard library, the latter of which lives on in Rails. If you tend to be pessimistic (I'm sorry, I meant realistic), then the Wrong testing framework might be your cup of tea. Or perhaps you're hungry and in the mood for something more substantial, in which case a side of Bacon might be what you need. At the end of the day, it doesn't matter which framework you choose as long as you cultivate your testing skills. The reason we choose RSpec is for its transparency. Just like Ruby itself, RSpec was written to be pleasant to read and write. It's easy to write Rspec tests that are clear and understandable. This might seem like a simple reason to choose a framework, but the simplicity of this choice is a proxy for deeper and more fundamental goals to programming. First, transparency means that testing is easier to adopt as a beginner. The sooner you adopt testing, the sooner you can be sure that your application works as intended. Second, transparency means that the intentions and targets of your tests are clear to you and to your collaborators. Not only is this helpful in developing and testing for edge cases, but it can also make it much easier to maintain a test suite as your application grows. An evolving and well-maintained test suite provides your application with a safety net as it too evolves and grows. A well-maintained test suite ensures that your code can meet regressions with aplomb and can remain adaptable to inevitable change. TLDR: RSpec is easy to learn, easy to write, and easy to maintain. But enough proselytizing. Strap your helmet and buckle up; we're going to jump right in. Installing RSpecBoot up your terminal and punch in Finally,
That's it. Within two steps, you're up and running with RSpec. That was so hard, wasn't it? Basic syntaxHow 'bout a test to see the syntax? Create a new directory called "ruby_testing", change into it, and initiate RSpec.
As expected, the output will read: create .rspec
create spec/spec_helper.rb Run the tests from your terminal by using the
Let's add our first test. Let's say we want to create a calculator with a few methods that we want to test. True to TDD, we will write the tests prior to the code. The #spec/calculator_spec.rb
RSpec.describe Calculator do
describe "#add" do
it "returns the sum of two numbers" do
calculator = Calculator.new
expect(calculator.add(5, 2)).to eql(7)
end
end
end Let's go line by line. First, #spec/calculator_spec.rb
describe Calculator do
#...
end The
Simple, isn't it? One more time, from the top:
Passing codeLet's move on. Run
So our first test returned an error. This is unsurprising. #lib/calculator.rb
class Calculator
def add(a,b)
end
end Finally, we must also tell the spec where the #spec/calculator_spec.rb
require './lib/calculator'
describe Calculator do
#...
end If you were to run
Our first failure is denoted by the Getting this method to "green" shouldn't be too difficult. RSpec clearly provides a reason for the failure: it expected the output to be #lib/calculator.rb
class Calculator
def add(a,b)
a + b #=> add this
end
end Then, run the test again to get a single dot, letting you know that your test has passed:
At this point, refactoring isn't necessary. The AssignmentsIt's time to put your newfound knowledge to good use. Let's break our
#spec/calculator_spec.rb
describe Calculator do
describe "#add" do
it "returns the sum of two numbers" do
#removed for brevity
end
#add this
it "returns the sum of more than two numbers" do
calculator = Calculator.new
expect(calculator.add(2, 5, 7)).to eql(14)
end
end
end
Additional ResourcesThis section contains helpful links to other content. It isn't required, so consider it supplemental for if you need to dive deeper into something
|
We're going to reopen this issue when this course is merged back into the curriculum repo (commit history will be preserved) |
🎉 |
Hope yall approve of my matchers lesson. IntroductionIn the previous lesson, we went over the basics of writing tests with RSpec. In this lesson, we will introduce you to RSpec matchers. There are tons of RSpec matchers and we couldn't possibly cover all of them in this lesson but I encourage you to take a look at the entire list of RSpec matchers Learning Outcomes:
RSpec MatchersWhy do you need to know about RSpec matchers?You may be asking yourself "Why do I need to know about matchers?" Well, matchers are a very important part of an expectation. Without them, you wouldn't be able to test anything! What are RSpec matchers?To understand matchers well, we need to take a step back. Rspec gives you two methods for your expectations describe "An example of basic matchers" do
it "Shows some matchers" do
#{matcher}
# |
# V
expect(something).to be_true
expect(something).to eq(3)
expect(something).to_not raise_error(SomeError)
end
end RSpec also gives you access to some special matchers when you have a predicate (boolean) method. Let's say you have a calculator class, and that class has two methods Let's take a look at those matchers in action. describe "An example of predicate matchers" do
it "should add two numbers and be even" do
#{matcher}
# |
# V
expect(@calculator.add(2,2)).to be_even
expect(@calculator.add(2,2)).to_not be_odd
end
end As you can see there's not much to the basic matchers but they are essential to testing and making sure you're comfortable with matchers is a good step towards testing your applications well. Basic RSpec matchersI have just gone over some of the very basic matchers built into RSpec. There are a ton more, but these are the most common ones you may encounter in the wild. Run through this list of matchers and make sure you understand which part of the expectation is a matcher describe "The most common RSpec matcher" do
it "Shows some more matchers" do
expect(array).to all(matcher)
expect(actual).to be > expected # (also works with =, <=, and ==)
expect(actual).to be_a(type)
expect(actual).to be_truthy
expect(actual).to be_falsy
expect(actual).to be_nil
expect(actual).to be_between(min, max)
expect(actual).to be_within(delta).of(expected)
expect { block }.to change(receiver, message, &block)
expect(actual).to contain_exactly(expected)
expect(range).to cover(actual_value)
expect(actual).to eq(expected)
expect(actual).to exist expect(actual).to have_attributes(key/value pairs)
expect(actual).to include(*expected)
expect(actual).to match(regex)
expect { block }.to output(value).to_stdout # also to_stderr
expect { block }.to raise_error(exception)
expect(actual).to satisfy { block }
end
end Assignments
Additional Resources
|
Hey @Deetss, the lesson looks great 😍 It would probably be worth wrapping any expectations in examples within Thats the only thing I notice, everything else looks good. Nice work man! |
Okay awesome! Thanks for y'all feedback! |
Test-Driven DevelopmentIntroductionHopefully, you've been having fun developing in Ruby thus far. Perhaps one thing you may not have enjoyed as much, though, is having to run your script on the command line, running through each step manually, only to find that it doesn't return what you expected. And then comes the even-less-fun part: You tug at your hair a bit, change a few variables, and run your script again through each step, hoping that the results are correct. Folks, we're here to tell you there IS better. Hoping is for that exam you didn't study for and took by the seat of your pants. Knowing is test-driven development. Learning Outcomes
What is Test-Driven Development?Test-Driven Development (TDD) is a process and technique of software development that relies on the repetition of a very short and specific development cycle. In each cycle, requirements (i.e., what you want your code to do) are turned into specific test cases first. These requirements could be anything from an entire feature that requires end-to-end (E2E) testing, such as a tests that cover a user logging into your website succesfully AND unsuccessfully, to a new Ruby class you've devised, for which unit tests might suffice. Either way, the test suite for these requirements fail initially, since actual code hasn't been written yet. Once the code is written and passes our test suite, you can move onto refactoring. As you might have guessed, running the test suite against the changes we make to our features or units enables us to refactor while making sure everything still works. Colloquially, this process is often referred to as the "red-green-refactor" cycle. That's all it is, in a nutshell: automated tests drive the design of software. You don't need to know how the entire architecture of your sweet, new, industry-breaking application will work. Your application only has to be broken down, step-by-step, until small units are identified and covered by tests. Why Is It Important?Even if TDD intuitively seems like good practice, its utility is hotly debated even today. No one is saying that tests aren't useful. The question is whether or not tests should drive development, or whether or not it's important for them to come first. Many developers write tests after they've written their code. There is definitely a longer list of pros than cons for having tests in general—no one will disagree with that—so why should we test first? Here are some reasons we think it might be important for you to implement TDD:
Assignments
|
We are seeking people to take charge of coordinating the creation of these lessons. If you would like to fill take this role, please let us know by commenting on this issue with your desire take ownership of these lessons.
For each lesson, reply to this issue with:
An Introduction for the lesson
A brief summary about what the lesson is about and why the topics or concepts it teaches are important.
Learning Outcomes
A list of bullet points of what the student is expected to know or be able to do by the end of this lesson
Content for the lesson
Explanations of the main concepts in the lesson, include code snippets and easy to understand metaphors where applicable.
Assignment
Either a list of links to resources the user will go through to learn about the topic of this lesson more in depth. Have no more than 5 resources, ideally no more than three. Or an exercise the student should do to solidify their understanding of the lesson content.
Additional Resources
A list of links to other resources which are valuable and or complement the assignment resources. Link to no more than three additional resources to avoid this section becoming too cluttered.
List of lessons:
The text was updated successfully, but these errors were encountered: