{"id":13880053,"url":"https://github.com/rspec/rspec-expectations","last_synced_at":"2025-08-06T15:31:46.665Z","repository":{"id":425333,"uuid":"238986","full_name":"rspec/rspec-expectations","owner":"rspec","description":"Provides a readable API to express expected outcomes of a code example","archived":true,"fork":false,"pushed_at":"2024-11-30T12:37:23.000Z","size":5706,"stargazers_count":1257,"open_issues_count":0,"forks_count":387,"subscribers_count":41,"default_branch":"main","last_synced_at":"2025-08-03T01:32:30.575Z","etag":null,"topics":["rspec","ruby"],"latest_commit_sha":null,"homepage":"https://rspec.info","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rspec.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["JonRowe","benoittgt"],"open_collective":"rspec"}},"created_at":"2009-06-29T15:58:17.000Z","updated_at":"2025-07-27T09:30:01.000Z","dependencies_parsed_at":"2023-07-05T14:53:35.290Z","dependency_job_id":"fabeafb1-fa5d-4af6-bf50-9eae1100dba0","html_url":"https://github.com/rspec/rspec-expectations","commit_stats":{"total_commits":2208,"total_committers":185,"mean_commits":"11.935135135135136","dds":0.6847826086956521,"last_synced_commit":"ba31727e856de42abb5a2e6566855f0831e1a619"},"previous_names":[],"tags_count":130,"template":false,"template_full_name":null,"purl":"pkg:github/rspec/rspec-expectations","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspec%2Frspec-expectations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspec%2Frspec-expectations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspec%2Frspec-expectations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspec%2Frspec-expectations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rspec","download_url":"https://codeload.github.com/rspec/rspec-expectations/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspec%2Frspec-expectations/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268505800,"owners_count":24260974,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-03T02:00:12.545Z","response_time":2577,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rspec","ruby"],"created_at":"2024-08-06T08:02:45.285Z","updated_at":"2025-08-06T15:31:46.616Z","avatar_url":"https://github.com/rspec.png","language":"Ruby","readme":"# RSpec Expectations [![Build Status](https://github.com/rspec/rspec-expectations/workflows/RSpec%20CI/badge.svg)](https://github.com/rspec/rspec-expectations/actions) [![Code Climate](https://codeclimate.com/github/rspec/rspec-expectations.svg)](https://codeclimate.com/github/rspec/rspec-expectations)\n\n**This is the old rspec expectations repository, please see the monorepo rspec/rspec for new issues and releases.**\n\nRSpec::Expectations lets you express expected outcomes on an object in an\nexample.\n\n```ruby\nexpect(account.balance).to eq(Money.new(37.42, :USD))\n```\n\n## Install\n\nIf you want to use rspec-expectations with rspec, just install the rspec gem\nand RubyGems will also install rspec-expectations for you (along with\nrspec-core and rspec-mocks):\n\n```shell\ngem install rspec\n```\n\nWant to run against the `main` branch? You'll need to include the dependent\nRSpec repos as well. Add the following to your `Gemfile`:\n\n```ruby\n%w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib|\n  gem lib, :git =\u003e \"https://github.com/rspec/#{lib}.git\", :branch =\u003e 'main'\nend\n```\n\nIf you want to use rspec-expectations with another tool, like Test::Unit,\nMinitest, or Cucumber, you can install it directly:\n\n```shell\ngem install rspec-expectations\n```\n\n## Contributing\n\nOnce you've set up the environment, you'll need to cd into the working\ndirectory of whichever repo you want to work in. From there you can run the\nspecs and cucumber features, and make patches.\n\nNOTE: You do not need to use rspec-dev to work on a specific RSpec repo. You\ncan treat each RSpec repo as an independent project.\n\n- [Build details](BUILD_DETAIL.md)\n- [Code of Conduct](CODE_OF_CONDUCT.md)\n- [Detailed contributing guide](CONTRIBUTING.md)\n- [Development setup guide](DEVELOPMENT.md)\n\n## Basic usage\n\nHere's an example using rspec-core:\n\n```ruby\nRSpec.describe Order do\n  it \"sums the prices of the items in its line items\" do\n    order = Order.new\n    order.add_entry(LineItem.new(:item =\u003e Item.new(\n      :price =\u003e Money.new(1.11, :USD)\n    )))\n    order.add_entry(LineItem.new(:item =\u003e Item.new(\n      :price =\u003e Money.new(2.22, :USD),\n      :quantity =\u003e 2\n    )))\n    expect(order.total).to eq(Money.new(5.55, :USD))\n  end\nend\n```\n\nThe `describe` and `it` methods come from rspec-core.  The `Order`, `LineItem`, `Item` and `Money` classes would be from _your_ code. The last line of the example\nexpresses an expected outcome. If `order.total == Money.new(5.55, :USD)`, then\nthe example passes. If not, it fails with a message like:\n\n```\n  expected: #\u003cMoney @value=5.55 @currency=:USD\u003e\n       got: #\u003cMoney @value=1.11 @currency=:USD\u003e\n```\n\n## Built-in matchers\n\n### Equivalence\n\n```ruby\nexpect(actual).to eq(expected)  # passes if actual == expected\nexpect(actual).to eql(expected) # passes if actual.eql?(expected)\nexpect(actual).not_to eql(not_expected) # passes if not(actual.eql?(expected))\n```\n\nNote: The new `expect` syntax no longer supports the `==` matcher.\n\n### Identity\n\n```ruby\nexpect(actual).to be(expected)    # passes if actual.equal?(expected)\nexpect(actual).to equal(expected) # passes if actual.equal?(expected)\n```\n\n### Comparisons\n\n```ruby\nexpect(actual).to be \u003e  expected\nexpect(actual).to be \u003e= expected\nexpect(actual).to be \u003c= expected\nexpect(actual).to be \u003c  expected\nexpect(actual).to be_within(delta).of(expected)\n```\n\n### Regular expressions\n\n```ruby\nexpect(actual).to match(/expression/)\n```\n\nNote: The new `expect` syntax no longer supports the `=~` matcher.\n\n### Types/classes\n\n```ruby\nexpect(actual).to be_an_instance_of(expected) # passes if actual.class == expected\nexpect(actual).to be_a(expected)              # passes if actual.kind_of?(expected)\nexpect(actual).to be_an(expected)             # an alias for be_a\nexpect(actual).to be_a_kind_of(expected)      # another alias\n```\n\n### Truthiness\n\n```ruby\nexpect(actual).to be_truthy   # passes if actual is truthy (not nil or false)\nexpect(actual).to be true     # passes if actual == true\nexpect(actual).to be_falsy    # passes if actual is falsy (nil or false)\nexpect(actual).to be false    # passes if actual == false\nexpect(actual).to be_nil      # passes if actual is nil\nexpect(actual).to_not be_nil  # passes if actual is not nil\n```\n\n### Expecting errors\n\n```ruby\nexpect { ... }.to raise_error\nexpect { ... }.to raise_error(ErrorClass)\nexpect { ... }.to raise_error(\"message\")\nexpect { ... }.to raise_error(ErrorClass, \"message\")\n```\n\n### Expecting throws\n\n```ruby\nexpect { ... }.to throw_symbol\nexpect { ... }.to throw_symbol(:symbol)\nexpect { ... }.to throw_symbol(:symbol, 'value')\n```\n\n### Yielding\n\n```ruby\nexpect { |b| 5.tap(\u0026b) }.to yield_control # passes regardless of yielded args\n\nexpect { |b| yield_if_true(true, \u0026b) }.to yield_with_no_args # passes only if no args are yielded\n\nexpect { |b| 5.tap(\u0026b) }.to yield_with_args(5)\nexpect { |b| 5.tap(\u0026b) }.to yield_with_args(Integer)\nexpect { |b| \"a string\".tap(\u0026b) }.to yield_with_args(/str/)\n\nexpect { |b| [1, 2, 3].each(\u0026b) }.to yield_successive_args(1, 2, 3)\nexpect { |b| { :a =\u003e 1, :b =\u003e 2 }.each(\u0026b) }.to yield_successive_args([:a, 1], [:b, 2])\n```\n\n### Predicate matchers\n\n```ruby\nexpect(actual).to be_xxx         # passes if actual.xxx?\nexpect(actual).to have_xxx(:arg) # passes if actual.has_xxx?(:arg)\n```\n\n### Ranges (Ruby \u003e= 1.9 only)\n\n```ruby\nexpect(1..10).to cover(3)\n```\n\n### Collection membership\n\n```ruby\n# exact order, entire collection\nexpect(actual).to eq(expected)\n\n# exact order, partial collection (based on an exact position)\nexpect(actual).to start_with(expected)\nexpect(actual).to end_with(expected)\n\n# any order, entire collection\nexpect(actual).to match_array(expected)\n\n# You can also express this by passing the expected elements\n# as individual arguments\nexpect(actual).to contain_exactly(expected_element1, expected_element2)\n\n # any order, partial collection\nexpect(actual).to include(expected)\n```\n\n#### Examples\n\n```ruby\nexpect([1, 2, 3]).to eq([1, 2, 3])            # Order dependent equality check\nexpect([1, 2, 3]).to include(1)               # Exact ordering, partial collection matches\nexpect([1, 2, 3]).to include(2, 3)            #\nexpect([1, 2, 3]).to start_with(1)            # As above, but from the start of the collection\nexpect([1, 2, 3]).to start_with(1, 2)         #\nexpect([1, 2, 3]).to end_with(3)              # As above but from the end of the collection\nexpect([1, 2, 3]).to end_with(2, 3)           #\nexpect({:a =\u003e 'b'}).to include(:a =\u003e 'b')     # Matching within hashes\nexpect(\"this string\").to include(\"is str\")    # Matching within strings\nexpect(\"this string\").to start_with(\"this\")   #\nexpect(\"this string\").to end_with(\"ring\")     #\nexpect([1, 2, 3]).to contain_exactly(2, 3, 1) # Order independent matches\nexpect([1, 2, 3]).to match_array([3, 2, 1])   #\n\n# Order dependent compound matchers\nexpect(\n  [{:a =\u003e 'hash'},{:a =\u003e 'another'}]\n).to match([a_hash_including(:a =\u003e 'hash'), a_hash_including(:a =\u003e 'another')])\n```\n\n## `should` syntax\n\nIn addition to the `expect` syntax, rspec-expectations continues to support the\n`should` syntax:\n\n```ruby\nactual.should eq expected\nactual.should be \u003e 3\n[1, 2, 3].should_not include 4\n```\n\nSee [detailed information on the `should` syntax and its usage.](https://github.com/rspec/rspec-expectations/blob/main/Should.md)\n\n## Compound Matcher Expressions\n\nYou can also create compound matcher expressions using `and` or `or`:\n\n``` ruby\nexpect(alphabet).to start_with(\"a\").and end_with(\"z\")\nexpect(stoplight.color).to eq(\"red\").or eq(\"green\").or eq(\"yellow\")\n```\n\n## Composing Matchers\n\nMany of the built-in matchers are designed to take matchers as\narguments, to allow you to flexibly specify only the essential\naspects of an object or data structure. In addition, all of the\nbuilt-in matchers have one or more aliases that provide better\nphrasing for when they are used as arguments to another matcher.\n\n### Examples\n\n```ruby\nexpect { k += 1.05 }.to change { k }.by( a_value_within(0.1).of(1.0) )\n\nexpect { s = \"barn\" }.to change { s }\n  .from( a_string_matching(/foo/) )\n  .to( a_string_matching(/bar/) )\n\nexpect([\"barn\", 2.45]).to contain_exactly(\n  a_value_within(0.1).of(2.5),\n  a_string_starting_with(\"bar\")\n)\n\nexpect([\"barn\", \"food\", 2.45]).to end_with(\n  a_string_matching(\"foo\"),\n  a_value \u003e 2\n)\n\nexpect([\"barn\", 2.45]).to include( a_string_starting_with(\"bar\") )\n\nexpect(:a =\u003e \"food\", :b =\u003e \"good\").to include(:a =\u003e a_string_matching(/foo/))\n\nhash = {\n  :a =\u003e {\n    :b =\u003e [\"foo\", 5],\n    :c =\u003e { :d =\u003e 2.05 }\n  }\n}\n\nexpect(hash).to match(\n  :a =\u003e {\n    :b =\u003e a_collection_containing_exactly(\n      a_string_starting_with(\"f\"),\n      an_instance_of(Integer)\n    ),\n    :c =\u003e { :d =\u003e (a_value \u003c 3) }\n  }\n)\n\nexpect { |probe|\n  [1, 2, 3].each(\u0026probe)\n}.to yield_successive_args( a_value \u003c 2, 2, a_value \u003e 2 )\n```\n\n## Usage outside rspec-core\n\nYou always need to load `rspec/expectations` even if you only want to use one part of the library:\n\n```ruby\nrequire 'rspec/expectations'\n```\n\nThen simply include `RSpec::Matchers` in any class:\n\n```ruby\nclass MyClass\n  include RSpec::Matchers\n\n  def do_something(arg)\n    expect(arg).to be \u003e 0\n    # do other stuff\n  end\nend\n```\n\n## Also see\n\n* [https://github.com/rspec/rspec](https://github.com/rspec/rspec)\n* [https://github.com/rspec/rspec-core](https://github.com/rspec/rspec-core)\n* [https://github.com/rspec/rspec-mocks](https://github.com/rspec/rspec-mocks)\n* [https://github.com/rspec/rspec-rails](https://github.com/rspec/rspec-rails)\n","funding_links":["https://github.com/sponsors/JonRowe","https://github.com/sponsors/benoittgt","https://opencollective.com/rspec"],"categories":["Ruby","Gems"],"sub_categories":["Testing"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frspec%2Frspec-expectations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frspec%2Frspec-expectations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frspec%2Frspec-expectations/lists"}