Testing Ruby with RSpec: The Complete Guide | Discount Coupon for Udemy Course
Master the art of test driven development (TDD) in Ruby using the RSpec Gem. No previous testing experience needed! | Discount Coupon for Udemy Coursebestseller
- 7.5 hours hours of on-demand video
- 5 article
- Full lifetime access
- Access on mobile and TV
- Certificate of completion
- 2 additional resources
- Master the syntax and structure of RSpec, the most popular Ruby Gem for testing
- Utilize test-driven development principles to design and implement clean test specs in Ruby
- Explore the wide collection of RSpec matchers available to test your code
- Reduce dependencies in your test suite by mocking objects with class and instance doubles
Welcome to Testing Ruby with RSpec: The Complete Guide!This course offers a comprehensive overview of the RSpec testing library for the Ruby programming language. RSpec is the most popular Ruby Gem of all time, with over 300 million downloads to date.If you're new to the topic, testing is the practice of "writing code that confirms that other code works as expected". Tests control for regressions, which are changes to the code that break the program. Tests give you the confidence to refactor existing code because you know that you will honor the original purpose of the code. The benefits of testing extend outside of your codebase. In this course, we'll cover test-driven development (TDD), a methodology in which we write our tests first, before the implementation. Test-driven development often leads to simpler, more decoupled code. Thus, testing can make you a better developer. Tests force you to think critically about the program and its features: the classes, the objects, the methods and more.Testing Ruby with RSpec begins with the RSpec essentials and proceeds to more complex topics including:InstallationProject InitializationTest-Driven Development (TDD)let variablesbefore and after HooksSubjectsShared ExamplesShared ContextBuilt-in MatchersMocks and DoublesInstance DoublesClass DoublesAs a software engineer and consultant who's worked with Ruby for 5+ years, I'm excited to introduce you to the awesome RSpec library, its elegant syntax, and all of its fun quirks.Thanks for checking out the course!Who this course is for:Intermediate Ruby developers interested in upgrading their skill setProgrammers who want to explore the fundamentals of testing and TDD
Sections are minimized for better readability, click the section title to view the course content
- Welcome to RSpec13:03
Welcome to the course! This lecture offers a quick introduction to the RSpec Gem as well as the benefits of testing. The various pieces of the library -- the core runner, expectations, and mocks -- are also introduced.
- About Me00:56
Get to know a little about your instructor.
- Unit Tests vs End-to-End (E2E) Tests09:16
Unit tests target a specific "unit" or piece of an application, such as a single class or method. They create isolation between coupled components to ensure each piece stands by itself. In comparison, end-to-end tests test an application or a large feature as a whole. Integration tests fall somewhere in the middle. In this lesson, we talk extensively about these types of tests and introduce the testing pyramid.
- Setup Ruby on macOS Computers01:45
This lecture offers a written tutorial for installing the Homebrew package manager, the rbenv Ruby version manager, and a modern version of Ruby on a macOS operating system. Windows users are advised to install Ruby through the RubyInstaller.org website.
- Setup Ruby on Windows Computers00:39
Learn how to install Ruby on a Windows computer.
- Install RSpec03:11
Ruby ships with a package manager called Gem. In this lesson, we utilize it to download the RSpec testing library.
- Install Visual Studio Code for macOS00:56
Visual Studio Code is a popular open-source text editor that is supported by Microsoft. This lesson covers the installation of the software on a macOS machine as well as the setup of the recommended Ruby extension for syntax highlighting. Windows users are advised to follow the instructions on the VSCode website to setup the app on their computers. If you prefer another text editor, that is totally fine as well.
- Start a Project with rspec --init10:17
The rspec --init command creates a base skeleton for an RSpec project. It creates a spec_helper.rb file where high-level, global RSpec settings for the project can be declared. There are some recommended settings that can be enabled by removing the =begin and =end lines in the file.
- Download Course Files (Optional)00:28
Download the complete course files here!
- Test-Driven Development05:28
Test-driven development (TDD) is a testing paradigm that argues that tests should be written first, before the code. This approach forces the developer to think critically about the implementation of the feature, one method at a time. This lesson describes the red-green-refactor pattern for practicing TDD. Red means a failing spec, green means a passing spec, and refactor means optimizing the code for clarity and efficiency.
- The describe Method04:42
The describe method on the top-level RSpec module creates an example group. An example group contains one or more examples. An example is the technical RSpec term for a test. In this lesson, we walk through the basic syntax and structure of setting up a sample example group (hey, that rhymes!)
- The it Method05:33
The it method creates an example (i.e. a focused test). The it method accepts a string -- ideally, it should be one that makes the example read like a sentence (i.e. it "should shuffle the deck" or it "can communicate with database"). After the string argument, pass the method a block. The block will contain the assertions for that example.
- The expect and eq Methods08:01
The expect method accepts what will be evaluated --it can be an object, a class, a method, or a plain Ruby expression like 1 + 1. The method returns an object that includes a to method, which is invoked with a matcher. A matcher is a type of assertion; there are various matchers in RSpec for equality, inequality, identity, inclusion and more. In this lesson, we create a sample Card object and write our first expectation for it.
- The describe, it and expect Methods1 questionThe RSpec expectation syntax has a little bit of a learning curve. In this assignment, you'll practice using the describe, it and expect methods to make some basic mathematical assertions.
- Reading Failures07:29
The rspec command in the Terminal can be followed with a path to a spec file's location. The command starts the RSpec test runner. The Terminal output includes a list of all examples that failed, including the line number that encountered an error or inconsistency. In this lesson, we read over the output and prepare to fix our failing specs.
- Making the Specs Pass08:57
It's time to make the Card class a reality! In this lesson, using our failing specs to guide us, we define a new Card class with a type attribute and a public reader method. It's important to not speed ahead and try to fix everything at once. Use each failure from the RSpec output to determine the next line of code to write. Fix one error, then run the rspec command again, and repeat.
- QUIZ: TDD and RSpec Methods9 questions
The time has come to challenge your knowledge of the course's material! This quiz dives into some of the higher-level concepts we've talked about so far (test-driven development, the testing pyramid) as well as RSpec-specific methods like describe, it, and expect.
- Multiple Examples in Example Group08:01
An example group can contain multiple examples. Some testing advocates argue that each example should only have one assertion. In this lesson, we expand the Card class to have a rank and a suit and write the corresponding specs.
- Fixing Failing Specs Again08:23
In this lesson, we continue the practice of using our failing specs to drive the development of the code. We update the Card class to have two initialize arguments, two reader methods, and two instance variables. We also discuss some of the drawbacks of our current examples, particularly the duplication.
- Making Specs Pass1 questionWe've now explored the basics of using test-driven development (TDD) to write our code. In this lesson, you'll practice these concepts by writing some Ruby code for some failing specs.
- Reducing Duplication - Before Hooks and Instance Variables10:58
Multiple examples in a test suite often rely on the same piece of data or a common object. Duplicating the code to create or access that object in each example creates a lot of duplication. To DRY up the code, this lesson introduces before hooks and instance variables. A hook is a piece of code that runs automatically at a specific time during testing. By default, the before hook executes a block of code before each example. Within the block, we assign values to instance variables to preserve values once the block execution ends. These instance variables are then available to be used within any examples defined below.
- Reducing Duplication: Helper Methods04:12
The block passed to the describe method provides a regular environment for Ruby expressions. We can define helper methods there to be invoked by the examples. Like a before block, this approach also creates separation between the examples.
- Problems With Mutation06:03
In this lesson, we discuss the limitations of a helper method approach. Subsequent calls to the same helper method in an example will return a new object each time. This makes it impossible to mutate a single object's state without using extra variables.
- Reducing Duplication: The let Method15:05
The let method defines a memoized, lazy-loaded variable that is available to all examples in the current context. The method accepts a symbol for the name of the variable and a block for the value that variable should be assigned. Lazy-loaded means the variable will not be declared until it is used in a specific example. Memoized means multiple references to the variable in the same example will not require a reevaluation of the block passed to the let method.
- Custom Error Messages04:39
To have RSpec display a custom error message when an expectation fails, pass a string as the second argument to the to method. In this lesson, we compare the different Terminal outputs for the default error message and our custom one.
- Removing Duplication5 questions
Test your knowledge of the concepts introduced in the previous lessons! This quiz tackles the topics of instance variables, helper methods, the let method, as well as broader concepts like memoization and lazy-loading.
- The context Method and Nested Describes08:17
describe method invocations can be nested inside other describe blocks. This is done to provide context about the specific circumstance or situation that an example is being run. context is an available alias for the describe method -- it can be used in the same fashion. In this lesson, we create nested describe blocks to test the even? predicate method in Ruby.
- before and after Hooks09:07
A hook allows the developer to run code during certain moments or events in the test suite's execution. The before and after run a block of code before or after a given criteria. When given a symbol of :example, the hook will run before / after each individual test. When given a symbol of :context, the hook will run once before / after all tests in the current block. In a real-life scenario, :context is used for high-level setup and teardown operations like connecting and disconnecting to a database (which is an expensive operation that you don't want to perform for each test).
- Nested Logic: Hooks12:00
Hooks gain an additional layer of complexity when describe / context blocks are nested within other describe / context blocks. The before(:context) hooks runs once before all tests in the current context (i.e. the current block). The before(:example) hook runs once before each test in the current context (which includes all nested blocks as well). If there is a before(:example) hook defined at multiple levels, each one will run in sequence, starting from the top-most block and proceeding downwards.
- Single Context Hooks1 questionTest your knowledge of RSpec hooks in both a regular and nested context!
- Multi-Context Hooks1 questionThis is a tough one! Test your knowledge of before and after hooks when dealing with multiple nested contexts.
- Nested Logic: Overwriting Let Variables08:53
let variables can be set to different values in nested blocks. Ruby / RSpec will search for the name in the current scope, then proceed upwards if it is unable to find it. Instead of using multiple variable names and adding confusion, it's much more elegant to reuse the let variable and assign it new, relevant values in each testing context.
- Implicit Subject07:37
The subject helper method lazily instantiates an instance of the class under test. This offers the developer several advantages including (1) one less let variable and (2) shorthand syntax for expectations that we'll discuss later. By default, subject assumes the class will have no initialization arguments. Within the same example, subject will memoize / cache the object when it's used multiple times. Between different examples, subject will instantiate a fresh object. In this lesson, we utilize subject to test a Ruby hash.
- Implicit Subject3 questionsUse RSpec's built-in subject helper method to access an instance of the class under test. Practice the syntax introduced in the previous lesson.
- Explicit Subject05:38
The subject method can be invoked outside of any example. The last evaluation of the block passed to the method will serve as its return value. This allows the developer to instantiate a custom object from the class under test to serve as the base "subject" for testing. A subject declared in an outer scope (i.e. an outer block) will be available to all inner, nested blocks.
- Explicit Subject1 questionOverwrite RSpec's default subject with an explicit instance of the class under test. Practice the syntax introduced in the previous lesson.
When a class is passed as an argument to the describe method, the class itself becomes available via the described_class method. It is advantageous to use described_class whenever the class is referenced because it makes the specs more adaptable to changes in business logic, such as the renaming of the class under test.
The use of either an implicit or explicit subject grants access to a special one-liner syntax for writing an example. First, the it method is passed a block without a string argument. Next, the method is_expected is invoked as a replacement for the expect syntax. Finally, a regular RSpec matcher (such as eq) is attached to the end. In this lesson, we demonstrate both syntactical options side by side.
- Shared Examples with include_examples10:11
The RSpec.shared_examples method is used to define commonly used examples that can be injected into multiple example groups. The method is passed a string identifier and a block where all the examples are declared. Later, the include_examples is invoked within the body of an example group and passed the string identifier. Multiple shared examples can be used; it is common to store these in a separate helper file that is imported by other spec files.
- Shared Context with include_context07:34
A complement to shared examples, the shared_context method allows for multiple example groups to rely on common boilerplate code. The developer can reduce duplication by declaring before blocks, instance variables, helper methods, and let variables in a shared context. The include_context method is then used to inject that context into multiple example groups.
- Subjects, Shared Examples, and Shared Context5 questionsTest your knowledge of the refactoring techniques introduced in this section.
- The not_to Method04:38
This section is focused on the matchers available in RSpec. A matcher is a type of assertion, expectation or validation. RSpec includes a variety of matchers -- everything from equality to inclusion to identity to error raising. The not_to method is an alternative to the to method that checks for the inverse or negative of a given matcher. For example, not_to eq will check for inequality.
- Equality Matchers I (eq and eql)05:30
The eq matcher checks only for value equality. The stricter eql matcher checks for both value and data type. For example, eq would consider the integer value 3 and the floating point value 3.0 to be equal. eql would not consider the two equal because they are of different data types.
- Equality Matchers II (equal and be)09:50
The equal matcher checks that two values are identical. To be identical, the values must both be the same object in the computer's memory. Identity is the strictest form of equality. In this lesson, we apply these matchers to arrays and introduce a real-life analogy of houses in a neighborhood.
- Comparison Matchers06:03
RSpec includes support for numerical comparisons like greater than and less than or equal to. Use the be matcher followed by the proper Ruby operator. For example, expect(10).to be >= 5 will pass if 10 is found to be greater than or equal to 5.
- Equality and Comparison Matchers6 questions
- Predicate Matchers07:45
A predicate method is one that returns a Boolean value -- either a true or a false. RSpec includes dynamic matchers for testing predicate methods. For any method, remove the question mark from the name and prefix it with be_. For example, the empty? method on an array can be tested with the predicate matcher be_empty.
- all Matcher06:20
The all matcher performs an aggregate check --- it validates that all elements in array fit some criteria. For example, expect([2, 4, 6]).to all(be_even) asserts that each value in an array is even. The matcher can also accept a mathematical comparison like be < 100 or be >= -2.
- be Matcher (Truthy, Falsy and Nil Values)07:23
Ruby has two falsy values: false and nil. All other objects are considered truthy, which means that they evaluate to true in a conditional context. In this lesson, we introduce the be_truthy and be_falsy matchers for asserting truthiness / falsiness as well as the be_nil matcher for explicit comparisons to nil.
- Predicate, all and be Matchers4 questionsTest your knowledge of the concepts introduced in the previous lessons.
- change Matcher10:02
One of the most powerful matchers in RSpec, the change matcher compares the value of something before and after an operation. Pass the expect method a block with some code that may mutate an object's state. Afterwards, invoke the change matcher with another block that describes what value is being tracked. Several comparison methods are available: the from / to combo as well as by.
- contain_exactly Matcher04:06
The contain_exactly matcher asserts that a sequence of elements is found within a collection, irrespective of order. The method is passed a comma-separated list of arguments to search for. If order matters, a more equality-focused matcher like eq would be used.
- start_with and end_with Matchers06:00
The start_with and end_with matchers check for the presence of a smaller subset of elements at the beginning or end of a data structure. For a string, the matchers will check for a substring of characters. For an array, the matchers will check for the presence of elements in sequential order.
- have_attributes Matcher04:35
The have_attributes matcher confirms that an object has a set of attributes with corresponding values. The method accepts a hash where the key is the name of the attribute and the value is the corresponding attribute value. When testing a custom object, the attributes have to be publicly accessible via reader methods to be able to be checked.
- include Matcher06:16
The include matcher checks for the inclusion of an object within a larger object. It can be used to check for a substring within a string, a value within an array, a key within a hash, and even a key-value pair within a hash. This matcher is not concerned with order, only with presence.
- raise_error Matcher09:11
The raise_error matcher checks that a block of code triggers an error. It is recommend to pass the matcher a specific error to watch out for. Otherwise, it becomes difficult to ascertain whether the expected error was the one that caused the spec to pass.
- respond_to Matcher09:01
The respond_to matcher verifies that an object can receive one or more given methods. The implementation and return values of the methods is not considered; this matcher checks only that the object has a method defined on its public interface. The additional with method confirms that the method is called with a specific number of arguments.
- satisfy Matcher09:42
The satisfy matcher is used to define custom assertions. This offers the best opportunity for defining expectations that tie in to the business logic of your app. In this lesson, we use satisfy to check if a string is a palindrome.
- not_to Method08:21
The not_to method tests for the negative or inverse of any RSpec matcher. For example, not_to include affirms that an array does not include a value. In this lesson, we practice the syntax while reviewing many of the matchers introduced in this section.
- Compound Expectations06:17
Compound expectations can chain together two or more expectations. The and method ensures both of the matchers pass while the or method ensures either of the matchers pass. In this lesson, we explore the syntax in the context of a randomness problem.
- Compound Expectations3 questionsTest your knowledge of compound expectations by writing some specs.
- Create a Test Double15:37
A double is a stand-in for a real object in a test. Doubles allow us to isolate specs to test app components (such as classes) independently. In this lesson, we create a sample stuntman double and walk through the syntax to permit and receive methods on it.
- Doubles2 questionsA double is a mock object that stands in for a real object in a test suite. Test your knowledge of creating doubles and assigning them methods in this assignment.
- Set up Our Test Movie08:44
In this lesson, we do some light prep work to set up the upcoming tests. All examples are tied to the real-life situation of a movie set with real actors and stunt doubles.
- Replacing an Object with a Double12:32
In this lesson, we replace our real object with a test double, connecting the ideas introduced in the last two lessons. The allow method defines a mock method on a double and the expect method affirms that it is called.
- Receive Counts07:26
In this lesson, we introduce new methods like at_most, at_least, once, and exactly to test how many times a method was received on a double. The method counts are not independent between different assertions so these methods cannot be stacked.
- The allow Method11:48
The allow method is incredibly versatile -- it can be customized to respond to different arguments as well as return different return values. In this lesson, we use the method to create a double that mocks the functionality of a Ruby array.
- Matching Arguments10:33
A method stub’s return value can be customized depending on the number or arguments, the type of arguments, or specific argument values. The with method specifies the number of expected arguments. In this lesson, we continue exploring how we can modify the allow method.
- Instance Doubles13:37
Verifying doubles are stricter alternatives to normal doubles. RSpec checks that the methods being stubbed are present on the underlying object. The instance_double method takes a class name or object as its argument. It verifies any method being stubbed would be present on an instance of that class.
- Class Doubles13:23
Class doubles mock a class and its class methods rather than its instance methods. One advantage of the class_double method is that the class itself have to be defined -- this allows for test-driven development.
- Spies I08:16
Spies are an alternate type of test double. They spy / observe the behavior of an object and all of the methods it receives. Spies follow a different pattern than a double -- they assert a message has been received after an action.
- Spies II09:44
In this lesson, we practice using spies with a Garage / Car class combo.
Congratulations on making it to the end of the course! I hope the course has been as fun to watch as it was for me to produce. Best of luck in all of your coding endeavors!
Explore the bonus content for the course!
Free Online Tools And Converters for your use
Input a string of text or a URL and encode the entered stringTry it
Input an encoded string of text or a URL and decode the entered stringTry it
Color Contrast Checker (WCAG)
Calculate the color contrast ration for your website (WCAG)Try it
Paste or upload an XML and have it formatted to a beautiful XML formatTry it
URL Slug Generator
Convert any title or sentence into a variety of slugs for your pages URLTry it
Draw an e-signature or type a signature for your online signatureTry it