README.md 4.56 KB
Newer Older
Tom Johnson's avatar
Tom Johnson committed
1 2
Testing your Samvera Application
================================
Tom Johnson's avatar
Tom Johnson committed
3 4 5 6

This repository supports a workshop given at
[Samvera Connect 2018](https://wiki.duraspace.org/display/samvera/Samvera+Connect+2018).

Tom Johnson's avatar
Outline  
Tom Johnson committed
7 8
This workshop builds on basic RSpec testing skills to help developers build robust test suites for Samvera applications. What should you test? How can you DRY up your test suite to streamline test development and maintenance? Developers will leave with an expanded sense of advanced testing tools and how to effectively use them in Samvera development.

Tom Johnson's avatar
Tom Johnson committed
9 10 11 12 13
## Prerequisites

**Please ensure you can do the following prior to the workshop:**

```sh
Tom Johnson's avatar
Outline  
Tom Johnson committed
14
git clone https://gitlab.com/no_reply/samvera-testing.git
Tom Johnson's avatar
Tom Johnson committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28
cd samvera-testing
bundle
bundle exec rake
```

### Prerequisites

If you have trouble with the above, please ensure the following are installed:

 * [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
 * Ruby 2.3+
   * You need a currently supported version of Ruby. If you don't already have this installed, please follow the Ruby installation [instructions](https://www.ruby-lang.org/en/documentation/installation/).
 * [Hyrax](https://github.com/samvera/hyrax#prerequisites) (_optional_)
   * Hyrax has various prerequisites; you may benefit from having all of these setup for a working Hyrax environment.
Tom Johnson's avatar
Outline  
Tom Johnson committed
29 30 31 32

## Agenda

### Getting started with RSpec
Tom Johnson's avatar
Tom Johnson committed
33 34 35 36 37 38 39 40 41 42 43

The Samvera community has largely converged on using RSpec as a testing
framework. RSpec provides a DSL for rapid Test Driven Development.

Some RSpec Resources:
  * [RSpec Core Documentation](https://relishapp.com/rspec/rspec-core/docs)
  * [RSpec Expectations Documentation](https://relishapp.com/rspec/rspec-expectations/docs)
  * [RSpec Mocks Documentation](https://relishapp.com/rspec/rspec-mocks/docs)
  * [RSpec Rails Documentation](https://relishapp.com/rspec/rspec-rails/docs)
  * [BetterSpecs](http://www.betterspecs.org/)

Tom Johnson's avatar
Tom Johnson committed
44
#### Your first test
Tom Johnson's avatar
Tom Johnson committed
45

Tom Johnson's avatar
Tom Johnson committed
46
Let's write an for an `Animal`. Our `Animal` will have one method `Animal#speak`. Write a _Unit Test_ for a `#speak` method with the behavior below at `spec/animal_spec.rb`; then add the implementation to make it pass.
Tom Johnson's avatar
Tom Johnson committed
47 48 49 50 51 52 53 54 55 56 57 58

```ruby
# lib/animal.rb
class Animal
  ##
  # @return [String]
  def speak
    "Hello!"
  end
end
```

Tom Johnson's avatar
Tom Johnson committed
59 60
An example of a unit test for `#speak` is in the branch `exercise-1`.

Tom Johnson's avatar
Tom Johnson committed
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
> **Types of Tests**
>
> There are many (overlapping, sometimes contradictory) taxonomies of tests.
> The thing they share is categorization based on the **System Under Test**.
> For our purposes, we want to consider tests based on the _size_ or
> _complexity_ of what we are testing:
>
>  * [Unit Tests](https://martinfowler.com/bliki/UnitTest.html) concern
>    themselves with a single `Class` or `#method`.
>  * [Integration Tests](https://martinfowler.com/bliki/IntegrationTest.html)
>    test the interaction of multiple separate but inter-dependent units.
>
> This simple distinction subsumes and elides many other types of tests commonly
> talked about under many different names: _feature tests_, _regression tests_,
> _system tests_, _smoke tests_, _acceptance tests_; as well as the
> Rails-specific types found in
> [RSpec Rails](https://relishapp.com/rspec/rspec-rails/docs)

Tom Johnson's avatar
Tom Johnson committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
#### Having a conversation

Let's add a simple `Conversation` class. Our `Conversation` will generate a
brief exchange between two animals using the `#chat` method. Let's write a test
for this method, then add the implementation as below:

```ruby
# lib/conversation.rb
class Conversation
  attr_accessor :speakers

  ##
  # @param [#speak] speaker_1
  # @param [#speak] speaker_2
  def initialize(speaker_1, speaker_2)
    self.speakers = [speaker_1, speaker_2]
  end

  ##
  # @return [String]
  def chat
    "#{speakers[0].speak}\n#{speakers[1].speak}\n"
  end
end
```

An example of a test for `#chat` is in the branch `exercise-2`.

**Discussion Topics**

  * Is this a unit test, or an integration test?
  * What is the purpose of the string arguments to the `describe` and `it` blocks?
  * What's going on in the line beginning `subject(:conversation)`?

Tom Johnson's avatar
Outline  
Tom Johnson committed
113 114
### Advanced RSpec
#### DRY Tests
Tom Johnson's avatar
Tom Johnson committed
115 116 117 118 119 120 121 122 123 124 125

  * Testing interfaces: `shared_examples`
  * Testing scenarios: `shared_context`
  * [One expectation per test?!](http://www.betterspecs.org/#single)

#### Test Doubles: Stubs, Mocks, Fakes

  * Real fakes
  * [Mocks aren't Stubs](https://martinfowler.com/articles/mocksArentStubs.html)
  * [RSpec Mock](https://relishapp.com/rspec/rspec-mocks/docs)

Tom Johnson's avatar
Outline  
Tom Johnson committed
126
### Factories
Tom Johnson's avatar
Tom Johnson committed
127 128 129

  * [Getting Started with FactoryBot](https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md)

Tom Johnson's avatar
Outline  
Tom Johnson committed
130
### Testing Samvera Applications
Tom Johnson's avatar
Tom Johnson committed
131 132

  * https://github.com/samvera-labs/hyrax-spec