html 服务器规范和rspec的备忘单

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了html 服务器规范和rspec的备忘单相关的知识,希望对你有一定的参考价值。

# Serverspec and RSpec Cheat Sheet

## Assertions

* `should` means "assert true".
* `should_not` means "assert false".

## Resources

http://serverspec.org/resource_types.html

### file

Files, directories, and devices.

```ruby
describe file('/path/to/file') do
  
  #INode type
  it { should be_file }       # or be_directory, or be_symlink
  it { should exist }
  
  #Permissions
  it { should be_owned_by 'username' }
  it { should be_grouped_into 'groupname' }
  
  it { should be_mode 440 }
  
  it { should be_readable }               # or be_writable or be_executable
  it { should be_readable.by('owner') }   # or 'group' or 'others'
  it { should be_readable.by_user('username') }
  
  #Links
  if { should be_linked_to '/path/to/target' }
  
  #Contents
  its(:md5sum)    { should eq '...' }    # or, and rspec matcher
  its(:sha256sum) { should eq '...' }
  its(:size)      { should < 1024 }
  its(:content)   { should match /some pattern/ }
  
end
```
    
### user

System users.

```ruby
describe user('username') do
  it { should exist }
  it { should belong_to_group 'group' }
  it { should have_home_directory '/home/username' }
  it { should have_login_shell '/bin/bash' }
  it { should have_authorized_key 'ssh-rsa ABCD... user@hostname' }
end
```
    
### group

System user groups.

```ruby
describe group('groupname') do
  it { should exist }
end
```
    
### packages

Software packages installed on the system.

```ruby
describe package('httpd') do
  it { should be_installed }
end
```

Select based on operating system:

```ruby
describe package('httpd'), :if => os[:family] == 'redhat' do
  it { should be_installed }
end

describe package('apache2'), :if => os[:family] == 'ubuntu' do
  it { should be_installed }
end
```
    
### port

Network ports

```ruby
describe port(80) do
  it { should be_listening }
end
```

### service

Installed services.

```ruby
describe service('httpd') do
  it { should be_running }
  it { should be_enabled }      # enabled to start when the OS boots.
end
```

### process

Currently running processes.

```ruby
describe process("memchached") do
  it { should be_running }
  
  # parameters from ps, see `man ps(1)`, under "STANDARD FORMAT SPECIFIERS"
  its(:user) { should eq 'root' }
  its(:args) { should match /-c 32000\b/ }
  its(:nice) { should > 10 }
end
```

### command

Run arbitrary commands and check the results.

```ruby
describe command('ls -al /') do
  its(:stdout) { should match /some pattern/ }
  its(:stderr) { should be_empty }
  its(:exit_status) { should eq 0 }
end
```
    
### host

Hosts on the network

```ruby
describe host('example.org') do
  it { should be_resolvable }
  
  # address
  its(:ipaddress) { should match /192\.168\.10\.10/ }     # could be IPv4 or IPv6
  its(:ipv4_address) { ... }
  its(:ipv6_address) { ... }

  # reachability
  it { should be_reachable }        # ping
  it { should be_reachable.with(
        :port => 53,                # required parameter
        # Optional params (default values shown)
        :proto => 'tcp',            # or 'udp'
        :timeout => 5               # in seconds.
  )}
end
```
    
## Matchers (rspec)

https://www.relishapp.com/rspec/rspec-expectations/v/3-4/docs/built-in-matchers

To try these outside of a serverspec test, you'll need to `require 'RSpec'`,
and replace `describe` with `RSpec.describe`.

### For strings

```ruby
describe 'foobar' do
  it { should eq 'foobar' }         # match using == operator
  it { should match /ooba/ }        # match using regex, anywhere in string.
  it { should_not match /^ooba$/ }  # anchor regex
  it { should_not be_empty }        # test for empty string: ""

  it { should start_with('fo') }
  it { should end_with('bar') }

  it { should be_a(String) }
end
```
        
### For numbers
        
```ruby
describe 10 do
  it { should eq 10 }
  it { should == 10 }             # same as above.
  it { should < 20 }
  it { should <= 10 }
  it { should > 0 }
  it { should >= 9 }

  it { should be_within(2).of(9) }
  it { should be_within(2).of(11) }

  it { should be_a(Numeric) }     # also consider: Float, Integer
  it { should be_an_instance_of(Fixnum) } # Direct class, no higher
end
```

### For arrays

```ruby
describe [1, 2, 3] do
  it { should_not be_empty }      # test for empty list: []

  it { should include(2) }        # membership test
  it { should_not include(0) }

  it { should all( be_an(Integer) ) }             # apply matcher to all elements
  it { should all( be_an(Integer).and be < 10 ) } # conjunction

  it { should start_with([1,2]) }
  it { should end_with([2,3]) }

  it { should be_an(Array) }
end
```

### For hashes

```ruby
describe ({ :a => 'A', :b => 2 }) do
  it { should have_key(:a) }
  it { should include(:a) }       # same as above
  it { should include(:b => 2) }  # test for presence of key and the value it maps to.
  it { should_not include(:b => 3) }
  it { should_not include(:c => 2) }

  it { should be_a(Hash) }
end
```

### The general purpose `satisfy` matcher

```ruby
describe(3.14159) do
  # Passes as long as the block returns true.
  it { should satisfy { |uut|
    uut.kind_of?(Numeric) and uut > 3 and uut < 3.2
  }}
end
```

### Combining expectations (`and`, `or`)

```ruby
describe("thunder") do
  it { should start_with("thun").and end_with("der") }
  it { should start_with("won").or start_with("thun") }
  it { should (start_with("won").or start_with("thun")).and end_with("der") }

  # with line breaks
  it { should (
      start_with("won").or \
      start_with("thun").or \
      start_with("pon")
    ).and (
      end_with("der")
    )
  }
end
```

### Defining custom matchers

```ruby
RSpec::Matchers.define :be_multiple_of do |expected|
  match do |actual|
    actual % expected == 0
  end

  # optional, override description
  description do
    "be multiple of #{expected}"
  end

  # optionally, override failure message:
  failure_message do |actual|
    "expected that #{actual} would be a multiple of #{expected}"
  end

  # optionally, override failure message when negated:
  failure_message_when_negated do |actual|
    "expected that #{actual} would not be a multiple of #{expected}"
  end
end

describe(9) do
  it { should be_multiple_of(3) }

  #Deliberate failures
  it { should be_multiple_of(2) }
  it { should_not be_multiple_of(3) }
end
```
<!DOCTYPE html >
<html>
    <!-- This was hacked together by hand after python-markdown output the bulk of it.
         Maybe someday I'll put together a better script to aut-generate this from markdown source. -->
    <head>
        <!-- github-markdown, plus github pygments -->
        <style type='text/css'>
        /* <![CDATA[ */
        @font-face {
  font-family: octicons-link;
  src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format('woff');
}

.markdown-body {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  color: #333;
  font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  font-size: 16px;
  line-height: 1.6;
  word-wrap: break-word;
}

.markdown-body a {
  background-color: transparent;
}

.markdown-body a:active,
.markdown-body a:hover {
  outline: 0;
}

.markdown-body strong {
  font-weight: bold;
}

.markdown-body h1 {
  font-size: 2em;
  margin: 0.67em 0;
}

.markdown-body img {
  border: 0;
}

.markdown-body hr {
  box-sizing: content-box;
  height: 0;
}

.markdown-body pre {
  overflow: auto;
}

.markdown-body code,
.markdown-body kbd,
.markdown-body pre {
  font-family: monospace, monospace;
  font-size: 1em;
}

.markdown-body input {
  color: inherit;
  font: inherit;
  margin: 0;
}

.markdown-body html input[disabled] {
  cursor: default;
}

.markdown-body input {
  line-height: normal;
}

.markdown-body input[type="checkbox"] {
  box-sizing: border-box;
  padding: 0;
}

.markdown-body table {
  border-collapse: collapse;
  border-spacing: 0;
}

.markdown-body td,
.markdown-body th {
  padding: 0;
}

.markdown-body * {
  box-sizing: border-box;
}

.markdown-body input {
  font: 13px / 1.4 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}

.markdown-body a {
  color: #4078c0;
  text-decoration: none;
}

.markdown-body a:hover,
.markdown-body a:active {
  text-decoration: underline;
}

.markdown-body hr {
  height: 0;
  margin: 15px 0;
  overflow: hidden;
  background: transparent;
  border: 0;
  border-bottom: 1px solid #ddd;
}

.markdown-body hr:before {
  display: table;
  content: "";
}

.markdown-body hr:after {
  display: table;
  clear: both;
  content: "";
}

.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
  margin-top: 15px;
  margin-bottom: 15px;
  line-height: 1.1;
}

.markdown-body h1 {
  font-size: 30px;
}

.markdown-body h2 {
  font-size: 21px;
}

.markdown-body h3 {
  font-size: 16px;
}

.markdown-body h4 {
  font-size: 14px;
}

.markdown-body h5 {
  font-size: 12px;
}

.markdown-body h6 {
  font-size: 11px;
}

.markdown-body blockquote {
  margin: 0;
}

.markdown-body ul,
.markdown-body ol {
  padding: 0;
  margin-top: 0;
  margin-bottom: 0;
}

.markdown-body ol ol,
.markdown-body ul ol {
  list-style-type: lower-roman;
}

.markdown-body ul ul ol,
.markdown-body ul ol ol,
.markdown-body ol ul ol,
.markdown-body ol ol ol {
  list-style-type: lower-alpha;
}

.markdown-body dd {
  margin-left: 0;
}

.markdown-body code {
  font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
  font-size: 12px;
}

.markdown-body pre {
  margin-top: 0;
  margin-bottom: 0;
  font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace;
}

.markdown-body .select::-ms-expand {
  opacity: 0;
}

.markdown-body .octicon {
  font: normal normal normal 16px/1 octicons-link;
  display: inline-block;
  text-decoration: none;
  text-rendering: auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.markdown-body .octicon-link:before {
  content: '\f05c';
}

.markdown-body:before {
  display: table;
  content: "";
}

.markdown-body:after {
  display: table;
  clear: both;
  content: "";
}

.markdown-body>*:first-child {
  margin-top: 0 !important;
}

.markdown-body>*:last-child {
  margin-bottom: 0 !important;
}

.markdown-body a:not([href]) {
  color: inherit;
  text-decoration: none;
}

.markdown-body .anchor {
  display: inline-block;
  padding-right: 2px;
  margin-left: -18px;
}

.markdown-body .anchor:focus {
  outline: none;
}

.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
  margin-top: 1em;
  margin-bottom: 16px;
  font-weight: bold;
  line-height: 1.4;
}

.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
  color: #000;
  vertical-align: middle;
  visibility: hidden;
}

.markdown-body h1:hover .anchor,
.markdown-body h2:hover .anchor,
.markdown-body h3:hover .anchor,
.markdown-body h4:hover .anchor,
.markdown-body h5:hover .anchor,
.markdown-body h6:hover .anchor {
  text-decoration: none;
}

.markdown-body h1:hover .anchor .octicon-link,
.markdown-body h2:hover .anchor .octicon-link,
.markdown-body h3:hover .anchor .octicon-link,
.markdown-body h4:hover .anchor .octicon-link,
.markdown-body h5:hover .anchor .octicon-link,
.markdown-body h6:hover .anchor .octicon-link {
  visibility: visible;
}

.markdown-body h1 {
  padding-bottom: 0.3em;
  font-size: 2.25em;
  line-height: 1.2;
  border-bottom: 1px solid #eee;
}

.markdown-body h1 .anchor {
  line-height: 1;
}

.markdown-body h2 {
  padding-bottom: 0.3em;
  font-size: 1.75em;
  line-height: 1.225;
  border-bottom: 1px solid #eee;
}

.markdown-body h2 .anchor {
  line-height: 1;
}

.markdown-body h3 {
  font-size: 1.5em;
  line-height: 1.43;
}

.markdown-body h3 .anchor {
  line-height: 1.2;
}

.markdown-body h4 {
  font-size: 1.25em;
}

.markdown-body h4 .anchor {
  line-height: 1.2;
}

.markdown-body h5 {
  font-size: 1em;
}

.markdown-body h5 .anchor {
  line-height: 1.1;
}

.markdown-body h6 {
  font-size: 1em;
  color: #777;
}

.markdown-body h6 .anchor {
  line-height: 1.1;
}

.markdown-body p,
.markdown-body blockquote,
.markdown-body ul,
.markdown-body ol,
.markdown-body dl,
.markdown-body table,
.markdown-body pre {
  margin-top: 0;
  margin-bottom: 16px;
}

.markdown-body hr {
  height: 4px;
  padding: 0;
  margin: 16px 0;
  background-color: #e7e7e7;
  border: 0 none;
}

.markdown-body ul,
.markdown-body ol {
  padding-left: 2em;
}

.markdown-body ul ul,
.markdown-body ul ol,
.markdown-body ol ol,
.markdown-body ol ul {
  margin-top: 0;
  margin-bottom: 0;
}

.markdown-body li>p {
  margin-top: 16px;
}

.markdown-body dl {
  padding: 0;
}

.markdown-body dl dt {
  padding: 0;
  margin-top: 16px;
  font-size: 1em;
  font-style: italic;
  font-weight: bold;
}

.markdown-body dl dd {
  padding: 0 16px;
  margin-bottom: 16px;
}

.markdown-body blockquote {
  padding: 0 15px;
  color: #777;
  border-left: 4px solid #ddd;
}

.markdown-body blockquote>:first-child {
  margin-top: 0;
}

.markdown-body blockquote>:last-child {
  margin-bottom: 0;
}

.markdown-body table {
  display: block;
  width: 100%;
  overflow: auto;
  word-break: normal;
  word-break: keep-all;
}

.markdown-body table th {
  font-weight: bold;
}

.markdown-body table th,
.markdown-body table td {
  padding: 6px 13px;
  border: 1px solid #ddd;
}

.markdown-body table tr {
  background-color: #fff;
  border-top: 1px solid #ccc;
}

.markdown-body table tr:nth-child(2n) {
  background-color: #f8f8f8;
}

.markdown-body img {
  max-width: 100%;
  box-sizing: content-box;
  background-color: #fff;
}

.markdown-body code {
  padding: 0;
  padding-top: 0.2em;
  padding-bottom: 0.2em;
  margin: 0;
  font-size: 85%;
  background-color: rgba(0,0,0,0.04);
  border-radius: 3px;
}

.markdown-body code:before,
.markdown-body code:after {
  letter-spacing: -0.2em;
  content: "\00a0";
}

.markdown-body pre>code {
  padding: 0;
  margin: 0;
  font-size: 100%;
  word-break: normal;
  white-space: pre;
  background: transparent;
  border: 0;
}

.markdown-body .highlight {
  margin-bottom: 16px;
}

.markdown-body .highlight pre,
.markdown-body pre {
  padding: 16px;
  overflow: auto;
  font-size: 85%;
  line-height: 1.45;
  background-color: #f7f7f7;
  border-radius: 3px;
}

.markdown-body .highlight pre {
  margin-bottom: 0;
  word-break: normal;
}

.markdown-body pre {
  word-wrap: normal;
}

.markdown-body pre code {
  display: inline;
  max-width: initial;
  padding: 0;
  margin: 0;
  overflow: initial;
  line-height: inherit;
  word-wrap: normal;
  background-color: transparent;
  border: 0;
}

.markdown-body pre code:before,
.markdown-body pre code:after {
  content: normal;
}

.markdown-body kbd {
  display: inline-block;
  padding: 3px 5px;
  font-size: 11px;
  line-height: 10px;
  color: #555;
  vertical-align: middle;
  background-color: #fcfcfc;
  border: solid 1px #ccc;
  border-bottom-color: #bbb;
  border-radius: 3px;
  box-shadow: inset 0 -1px 0 #bbb;
}

.markdown-body .pl-c {
  color: #969896;
}

.markdown-body .pl-c1,
.markdown-body .pl-s .pl-v {
  color: #0086b3;
}

.markdown-body .pl-e,
.markdown-body .pl-en {
  color: #795da3;
}

.markdown-body .pl-s .pl-s1,
.markdown-body .pl-smi {
  color: #333;
}

.markdown-body .pl-ent {
  color: #63a35c;
}

.markdown-body .pl-k {
  color: #a71d5d;
}

.markdown-body .pl-pds,
.markdown-body .pl-s,
.markdown-body .pl-s .pl-pse .pl-s1,
.markdown-body .pl-sr,
.markdown-body .pl-sr .pl-cce,
.markdown-body .pl-sr .pl-sra,
.markdown-body .pl-sr .pl-sre {
  color: #183691;
}

.markdown-body .pl-v {
  color: #ed6a43;
}

.markdown-body .pl-id {
  color: #b52a1d;
}

.markdown-body .pl-ii {
  background-color: #b52a1d;
  color: #f8f8f8;
}

.markdown-body .pl-sr .pl-cce {
  color: #63a35c;
  font-weight: bold;
}

.markdown-body .pl-ml {
  color: #693a17;
}

.markdown-body .pl-mh,
.markdown-body .pl-mh .pl-en,
.markdown-body .pl-ms {
  color: #1d3e81;
  font-weight: bold;
}

.markdown-body .pl-mq {
  color: #008080;
}

.markdown-body .pl-mi {
  color: #333;
  font-style: italic;
}

.markdown-body .pl-mb {
  color: #333;
  font-weight: bold;
}

.markdown-body .pl-md {
  background-color: #ffecec;
  color: #bd2c00;
}

.markdown-body .pl-mi1 {
  background-color: #eaffea;
  color: #55a532;
}

.markdown-body .pl-mdr {
  color: #795da3;
  font-weight: bold;
}

.markdown-body .pl-mo {
  color: #1d3e81;
}

.markdown-body kbd {
  display: inline-block;
  padding: 3px 5px;
  font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace;
  line-height: 10px;
  color: #555;
  vertical-align: middle;
  background-color: #fcfcfc;
  border: solid 1px #ccc;
  border-bottom-color: #bbb;
  border-radius: 3px;
  box-shadow: inset 0 -1px 0 #bbb;
}

.markdown-body .task-list-item {
  list-style-type: none;
}

.markdown-body .task-list-item+.task-list-item {
  margin-top: 3px;
}

.markdown-body .task-list-item input {
  margin: 0 0.35em 0.25em -1.6em;
  vertical-align: middle;
}

.markdown-body :checked+.radio-label {
  z-index: 1;
  position: relative;
  border-color: #4078c0;
}

.codehilite .hll { background-color: #ffffcc }
.codehilite .c { color: #999988; font-style: italic } /* Comment */
.codehilite .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.codehilite .k { color: #000000; font-weight: bold } /* Keyword */
.codehilite .o { color: #000000; font-weight: bold } /* Operator */
.codehilite .cm { color: #999988; font-style: italic } /* Comment.Multiline */
.codehilite .cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */
.codehilite .c1 { color: #999988; font-style: italic } /* Comment.Single */
.codehilite .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
.codehilite .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.codehilite .ge { color: #000000; font-style: italic } /* Generic.Emph */
.codehilite .gr { color: #aa0000 } /* Generic.Error */
.codehilite .gh { color: #999999 } /* Generic.Heading */
.codehilite .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.codehilite .go { color: #888888 } /* Generic.Output */
.codehilite .gp { color: #555555 } /* Generic.Prompt */
.codehilite .gs { font-weight: bold } /* Generic.Strong */
.codehilite .gu { color: #aaaaaa } /* Generic.Subheading */
.codehilite .gt { color: #aa0000 } /* Generic.Traceback */
.codehilite .kc { color: #000000; font-weight: bold } /* Keyword.Constant */
.codehilite .kd { color: #000000; font-weight: bold } /* Keyword.Declaration */
.codehilite .kn { color: #000000; font-weight: bold } /* Keyword.Namespace */
.codehilite .kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */
.codehilite .kr { color: #000000; font-weight: bold } /* Keyword.Reserved */
.codehilite .kt { color: #445588; font-weight: bold } /* Keyword.Type */
.codehilite .m { color: #009999 } /* Literal.Number */
.codehilite .s { color: #d01040 } /* Literal.String */
.codehilite .na { color: #008080 } /* Name.Attribute */
.codehilite .nb { color: #0086B3 } /* Name.Builtin */
.codehilite .nc { color: #445588; font-weight: bold } /* Name.Class */
.codehilite .no { color: #008080 } /* Name.Constant */
.codehilite .nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */
.codehilite .ni { color: #800080 } /* Name.Entity */
.codehilite .ne { color: #990000; font-weight: bold } /* Name.Exception */
.codehilite .nf { color: #990000; font-weight: bold } /* Name.Function */
.codehilite .nl { color: #990000; font-weight: bold } /* Name.Label */
.codehilite .nn { color: #555555 } /* Name.Namespace */
.codehilite .nt { color: #000080 } /* Name.Tag */
.codehilite .nv { color: #008080 } /* Name.Variable */
.codehilite .ow { color: #000000; font-weight: bold } /* Operator.Word */
.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
.codehilite .mf { color: #009999 } /* Literal.Number.Float */
.codehilite .mh { color: #009999 } /* Literal.Number.Hex */
.codehilite .mi { color: #009999 } /* Literal.Number.Integer */
.codehilite .mo { color: #009999 } /* Literal.Number.Oct */
.codehilite .sb { color: #d01040 } /* Literal.String.Backtick */
.codehilite .sc { color: #d01040 } /* Literal.String.Char */
.codehilite .sd { color: #d01040 } /* Literal.String.Doc */
.codehilite .s2 { color: #d01040 } /* Literal.String.Double */
.codehilite .se { color: #d01040 } /* Literal.String.Escape */
.codehilite .sh { color: #d01040 } /* Literal.String.Heredoc */
.codehilite .si { color: #d01040 } /* Literal.String.Interpol */
.codehilite .sx { color: #d01040 } /* Literal.String.Other */
.codehilite .sr { color: #009926 } /* Literal.String.Regex */
.codehilite .s1 { color: #d01040 } /* Literal.String.Single */
.codehilite .ss { color: #990073 } /* Literal.String.Symbol */
.codehilite .bp { color: #999999 } /* Name.Builtin.Pseudo */
.codehilite .vc { color: #008080 } /* Name.Variable.Class */
.codehilite .vg { color: #008080 } /* Name.Variable.Global */
.codehilite .vi { color: #008080 } /* Name.Variable.Instance */
.codehilite .il { color: #009999 } /* Literal.Number.Integer.Long */


        /* ]]> */
        </style>

        <style type='text/css'>
        /* <![CDATA[ */
        .codehilite {
            page-break-inside: avoid;
            page-break-before: avoid;
            page-break-after: auto;
            break-inside: avoid;
            break-before: avoid;
            break-after: auto;
        }

        h1, h2, h3, h4, h5 {
            page-break-after: avoid;
            break-after: avoid;
            page-break-before: auto;
            break-before: auto;
        }

        section.no-break {
            page-break-inside: avoid;
            break-inside: avoid;
        }

        #content {
            column-count: 2;
            -moz-column-count: 2;
            -moz-column-gap: 2.5em;
            -moz-column-rule: 1px solid #eee;
        }

        .markdown-body h1 {
            border-bottom-color: black;
        }

        .markdown-body h2 {
            border-bottom: 4px solid black;
        }

        .markdown-body h3 {
            border-bottom: 2px solid black;
        }

        @media print {
            .markdown-body pre {
                background-color: #ddd;
                border: 1px solid #999;
            }

            #content {
                -moz-column-rule: 1px solid #333;
            }
        }

        /* ]]> */
        </style>
    </head>
    <body class='markdown-body'>
    <h1>Serverspec and RSpec Cheat Sheet</h1>
    <div id='content'>
<h2>Assertions</h2>
<ul>
<li><code>should</code> means "assert true".</li>
<li><code>should_not</code> means "assert false".</li>
</ul>
<h2>Resources</h2>
<p><a href="http://serverspec.org/resource_types.html">http://serverspec.org/resource_types.html</a></p>

<section class='no-break'>
<h3>file</h3>
<p>Files, directories, and devices.</p>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="n">file</span><span class="p">(</span><span class="s1">&#39;/path/to/file&#39;</span><span class="p">)</span> <span class="k">do</span>

  <span class="c1">#INode type</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_file</span> <span class="p">}</span>       <span class="c1"># or be_directory, or be_symlink</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">exist</span> <span class="p">}</span>

  <span class="c1">#Permissions</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_owned_by</span> <span class="s1">&#39;username&#39;</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_grouped_into</span> <span class="s1">&#39;groupname&#39;</span> <span class="p">}</span>

  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_mode</span> <span class="mi">440</span> <span class="p">}</span>

  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_readable</span> <span class="p">}</span>               <span class="c1"># or be_writable or be_executable</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_readable</span><span class="o">.</span><span class="n">by</span><span class="p">(</span><span class="s1">&#39;owner&#39;</span><span class="p">)</span> <span class="p">}</span>   <span class="c1"># or &#39;group&#39; or &#39;others&#39;</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_readable</span><span class="o">.</span><span class="n">by_user</span><span class="p">(</span><span class="s1">&#39;username&#39;</span><span class="p">)</span> <span class="p">}</span>

  <span class="c1">#Links</span>
  <span class="k">if</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_linked_to</span> <span class="s1">&#39;/path/to/target&#39;</span> <span class="p">}</span>

  <span class="c1">#Contents</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:md5sum</span><span class="p">)</span>    <span class="p">{</span> <span class="n">should</span> <span class="n">eq</span> <span class="s1">&#39;...&#39;</span> <span class="p">}</span>    <span class="c1"># or, and rspec matcher</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:sha256sum</span><span class="p">)</span> <span class="p">{</span> <span class="n">should</span> <span class="n">eq</span> <span class="s1">&#39;...&#39;</span> <span class="p">}</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:size</span><span class="p">)</span>      <span class="p">{</span> <span class="n">should</span> <span class="o">&lt;</span> <span class="mi">1024</span> <span class="p">}</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:content</span><span class="p">)</span>   <span class="p">{</span> <span class="n">should</span> <span class="n">match</span> <span class="sr">/some pattern/</span> <span class="p">}</span>

<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>user</h3>
<p>System users.</p>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="n">user</span><span class="p">(</span><span class="s1">&#39;username&#39;</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">exist</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">belong_to_group</span> <span class="s1">&#39;group&#39;</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">have_home_directory</span> <span class="s1">&#39;/home/username&#39;</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">have_login_shell</span> <span class="s1">&#39;/bin/bash&#39;</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">have_authorized_key</span> <span class="s1">&#39;ssh-rsa ABCD... user@hostname&#39;</span> <span class="p">}</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>group</h3>
<p>System user groups.</p>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="n">group</span><span class="p">(</span><span class="s1">&#39;groupname&#39;</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">exist</span> <span class="p">}</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>packages</h3>
<p>Software packages installed on the system.</p>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="n">package</span><span class="p">(</span><span class="s1">&#39;httpd&#39;</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_installed</span> <span class="p">}</span>
<span class="k">end</span>
</pre></div>


<p>Select based on operating system:</p>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="n">package</span><span class="p">(</span><span class="s1">&#39;httpd&#39;</span><span class="p">),</span> <span class="ss">:if</span> <span class="o">=&gt;</span> <span class="n">os</span><span class="o">[</span><span class="ss">:family</span><span class="o">]</span> <span class="o">==</span> <span class="s1">&#39;redhat&#39;</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_installed</span> <span class="p">}</span>
<span class="k">end</span>

<span class="n">describe</span> <span class="n">package</span><span class="p">(</span><span class="s1">&#39;apache2&#39;</span><span class="p">),</span> <span class="ss">:if</span> <span class="o">=&gt;</span> <span class="n">os</span><span class="o">[</span><span class="ss">:family</span><span class="o">]</span> <span class="o">==</span> <span class="s1">&#39;ubuntu&#39;</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_installed</span> <span class="p">}</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>port</h3>
<p>Network ports</p>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="n">port</span><span class="p">(</span><span class="mi">80</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_listening</span> <span class="p">}</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>service</h3>
<p>Installed services.</p>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="n">service</span><span class="p">(</span><span class="s1">&#39;httpd&#39;</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_running</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_enabled</span> <span class="p">}</span>      <span class="c1"># enabled to start when the OS boots.</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>process</h3>
<p>Currently running processes.</p>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="n">process</span><span class="p">(</span><span class="s2">&quot;memchached&quot;</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_running</span> <span class="p">}</span>

  <span class="c1"># parameters from ps, see `man ps(1)`, under &quot;STANDARD FORMAT SPECIFIERS&quot;</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:user</span><span class="p">)</span> <span class="p">{</span> <span class="n">should</span> <span class="n">eq</span> <span class="s1">&#39;root&#39;</span> <span class="p">}</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:args</span><span class="p">)</span> <span class="p">{</span> <span class="n">should</span> <span class="n">match</span> <span class="sr">/-c 32000\b/</span> <span class="p">}</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:nice</span><span class="p">)</span> <span class="p">{</span> <span class="n">should</span> <span class="o">&gt;</span> <span class="mi">10</span> <span class="p">}</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>command</h3>
<p>Run arbitrary commands and check the results.</p>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="n">command</span><span class="p">(</span><span class="s1">&#39;ls -al /&#39;</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:stdout</span><span class="p">)</span> <span class="p">{</span> <span class="n">should</span> <span class="n">match</span> <span class="sr">/some pattern/</span> <span class="p">}</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:stderr</span><span class="p">)</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_empty</span> <span class="p">}</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:exit_status</span><span class="p">)</span> <span class="p">{</span> <span class="n">should</span> <span class="n">eq</span> <span class="mi">0</span> <span class="p">}</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>host</h3>
<p>Hosts on the network</p>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="n">host</span><span class="p">(</span><span class="s1">&#39;example.org&#39;</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_resolvable</span> <span class="p">}</span>

  <span class="c1"># address</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:ipaddress</span><span class="p">)</span> <span class="p">{</span> <span class="n">should</span> <span class="n">match</span> <span class="sr">/192\.168\.10\.10/</span> <span class="p">}</span>     <span class="c1"># could be IPv4 or IPv6</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:ipv4_address</span><span class="p">)</span> <span class="p">{</span> <span class="o">...</span> <span class="p">}</span>
  <span class="n">its</span><span class="p">(</span><span class="ss">:ipv6_address</span><span class="p">)</span> <span class="p">{</span> <span class="o">...</span> <span class="p">}</span>

  <span class="c1"># reachability</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_reachable</span> <span class="p">}</span>        <span class="c1"># ping</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_reachable</span><span class="o">.</span><span class="n">with</span><span class="p">(</span>
        <span class="ss">:port</span> <span class="o">=&gt;</span> <span class="mi">53</span><span class="p">,</span>                <span class="c1"># required parameter</span>
        <span class="c1"># Optional params (default values shown)</span>
        <span class="ss">:proto</span> <span class="o">=&gt;</span> <span class="s1">&#39;tcp&#39;</span><span class="p">,</span>            <span class="c1"># or &#39;udp&#39;</span>
        <span class="ss">:timeout</span> <span class="o">=&gt;</span> <span class="mi">5</span>               <span class="c1"># in seconds.</span>
  <span class="p">)}</span>
<span class="k">end</span>
</pre></div>
</section>


<h2>Matchers (rspec)</h2>
<p><a href="https://www.relishapp.com/rspec/rspec-expectations/v/3-4/docs/built-in-matchers"> https://www.relishapp.com/rspec/rspec-expectations/v/3-4/docs/built-in-matchers </a></p>
<p>To try these outside of a serverspec test, you'll need to <code>require 'RSpec'</code>,
and replace <code>describe</code> with <code>RSpec.describe</code>.</p>

<section class='no-break'>
<h3>For strings</h3>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="s1">&#39;foobar&#39;</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">eq</span> <span class="s1">&#39;foobar&#39;</span> <span class="p">}</span>         <span class="c1"># match using == operator</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">match</span> <span class="sr">/ooba/</span> <span class="p">}</span>        <span class="c1"># match using regex, anywhere in string.</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should_not</span> <span class="n">match</span> <span class="sr">/^ooba$/</span> <span class="p">}</span>  <span class="c1"># anchor regex</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should_not</span> <span class="n">be_empty</span> <span class="p">}</span>        <span class="c1"># test for empty string: &quot;&quot;</span>

  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">start_with</span><span class="p">(</span><span class="s1">&#39;fo&#39;</span><span class="p">)</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">end_with</span><span class="p">(</span><span class="s1">&#39;bar&#39;</span><span class="p">)</span> <span class="p">}</span>

  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_a</span><span class="p">(</span><span class="nb">String</span><span class="p">)</span> <span class="p">}</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>For numbers</h3>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="mi">10</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">eq</span> <span class="mi">10</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="o">==</span> <span class="mi">10</span> <span class="p">}</span>             <span class="c1"># same as above.</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="o">&lt;</span> <span class="mi">20</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="o">&lt;=</span> <span class="mi">10</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="o">&gt;=</span> <span class="mi">9</span> <span class="p">}</span>

  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_within</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">of</span><span class="p">(</span><span class="mi">9</span><span class="p">)</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_within</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">of</span><span class="p">(</span><span class="mi">11</span><span class="p">)</span> <span class="p">}</span>

  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_a</span><span class="p">(</span><span class="no">Numeric</span><span class="p">)</span> <span class="p">}</span>     <span class="c1"># also consider: Float, Integer</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_an_instance_of</span><span class="p">(</span><span class="no">Fixnum</span><span class="p">)</span> <span class="p">}</span> <span class="c1"># Direct class, no higher</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>For arrays</h3>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="o">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="o">]</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should_not</span> <span class="n">be_empty</span> <span class="p">}</span>      <span class="c1"># test for empty list: []</span>

  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="kp">include</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="p">}</span>        <span class="c1"># membership test</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should_not</span> <span class="kp">include</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">}</span>

  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">all</span><span class="p">(</span> <span class="n">be_an</span><span class="p">(</span><span class="nb">Integer</span><span class="p">)</span> <span class="p">)</span> <span class="p">}</span>             <span class="c1"># apply matcher to all elements</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">all</span><span class="p">(</span> <span class="n">be_an</span><span class="p">(</span><span class="nb">Integer</span><span class="p">)</span><span class="o">.</span><span class="n">and</span> <span class="n">be</span> <span class="o">&lt;</span> <span class="mi">10</span> <span class="p">)</span> <span class="p">}</span> <span class="c1"># conjunction</span>

  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">start_with</span><span class="p">(</span><span class="o">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="o">]</span><span class="p">)</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">end_with</span><span class="p">(</span><span class="o">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="o">]</span><span class="p">)</span> <span class="p">}</span>

  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_an</span><span class="p">(</span><span class="nb">Array</span><span class="p">)</span> <span class="p">}</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>For hashes</h3>
<div class="codehilite"><pre><span></span><span class="n">describe</span> <span class="p">({</span> <span class="ss">:a</span> <span class="o">=&gt;</span> <span class="s1">&#39;A&#39;</span><span class="p">,</span> <span class="ss">:b</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">})</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">have_key</span><span class="p">(</span><span class="ss">:a</span><span class="p">)</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="kp">include</span><span class="p">(</span><span class="ss">:a</span><span class="p">)</span> <span class="p">}</span>       <span class="c1"># same as above</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="kp">include</span><span class="p">(</span><span class="ss">:b</span> <span class="o">=&gt;</span> <span class="mi">2</span><span class="p">)</span> <span class="p">}</span>  <span class="c1"># test for presence of key and the value it maps to.</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should_not</span> <span class="kp">include</span><span class="p">(</span><span class="ss">:b</span> <span class="o">=&gt;</span> <span class="mi">3</span><span class="p">)</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should_not</span> <span class="kp">include</span><span class="p">(</span><span class="ss">:c</span> <span class="o">=&gt;</span> <span class="mi">2</span><span class="p">)</span> <span class="p">}</span>

  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_a</span><span class="p">(</span><span class="no">Hash</span><span class="p">)</span> <span class="p">}</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>The general purpose <code>satisfy</code> matcher</h3>
<div class="codehilite"><pre><span></span><span class="n">describe</span><span class="p">(</span><span class="mi">3</span><span class="o">.</span><span class="mi">14159</span><span class="p">)</span> <span class="k">do</span>
  <span class="c1"># Passes as long as the block returns true.</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">satisfy</span> <span class="p">{</span> <span class="o">|</span><span class="n">uut</span><span class="o">|</span>
    <span class="n">uut</span><span class="o">.</span><span class="n">kind_of?</span><span class="p">(</span><span class="no">Numeric</span><span class="p">)</span> <span class="ow">and</span> <span class="n">uut</span> <span class="o">&gt;</span> <span class="mi">3</span> <span class="ow">and</span> <span class="n">uut</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="o">.</span><span class="mi">2</span>
  <span class="p">}}</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>Combining expectations (<code>and</code>, <code>or</code>)</h3>
<div class="codehilite"><pre><span></span><span class="n">describe</span><span class="p">(</span><span class="s2">&quot;thunder&quot;</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">start_with</span><span class="p">(</span><span class="s2">&quot;thun&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">and</span> <span class="n">end_with</span><span class="p">(</span><span class="s2">&quot;der&quot;</span><span class="p">)</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">start_with</span><span class="p">(</span><span class="s2">&quot;won&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">or</span> <span class="n">start_with</span><span class="p">(</span><span class="s2">&quot;thun&quot;</span><span class="p">)</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="p">(</span><span class="n">start_with</span><span class="p">(</span><span class="s2">&quot;won&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">or</span> <span class="n">start_with</span><span class="p">(</span><span class="s2">&quot;thun&quot;</span><span class="p">))</span><span class="o">.</span><span class="n">and</span> <span class="n">end_with</span><span class="p">(</span><span class="s2">&quot;der&quot;</span><span class="p">)</span> <span class="p">}</span>

  <span class="c1"># with line breaks</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="p">(</span>
      <span class="n">start_with</span><span class="p">(</span><span class="s2">&quot;won&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">or</span> <span class="p">\</span>
      <span class="n">start_with</span><span class="p">(</span><span class="s2">&quot;thun&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">or</span> <span class="p">\</span>
      <span class="n">start_with</span><span class="p">(</span><span class="s2">&quot;pon&quot;</span><span class="p">)</span>
    <span class="p">)</span><span class="o">.</span><span class="n">and</span> <span class="p">(</span>
      <span class="n">end_with</span><span class="p">(</span><span class="s2">&quot;der&quot;</span><span class="p">)</span>
    <span class="p">)</span>
  <span class="p">}</span>
<span class="k">end</span>
</pre></div>
</section>


<section class='no-break'>
<h3>Defining custom matchers</h3>
<div class="codehilite"><pre><span></span><span class="no">RSpec</span><span class="o">::</span><span class="no">Matchers</span><span class="o">.</span><span class="n">define</span> <span class="ss">:be_multiple_of</span> <span class="k">do</span> <span class="o">|</span><span class="n">expected</span><span class="o">|</span>
  <span class="n">match</span> <span class="k">do</span> <span class="o">|</span><span class="n">actual</span><span class="o">|</span>
    <span class="n">actual</span> <span class="o">%</span> <span class="n">expected</span> <span class="o">==</span> <span class="mi">0</span>
  <span class="k">end</span>

  <span class="c1"># optional, override description</span>
  <span class="n">description</span> <span class="k">do</span>
    <span class="s2">&quot;be multiple of </span><span class="si">#{</span><span class="n">expected</span><span class="si">}</span><span class="s2">&quot;</span>
  <span class="k">end</span>

  <span class="c1"># optionally, override failure message:</span>
  <span class="n">failure_message</span> <span class="k">do</span> <span class="o">|</span><span class="n">actual</span><span class="o">|</span>
    <span class="s2">&quot;expected that </span><span class="si">#{</span><span class="n">actual</span><span class="si">}</span><span class="s2"> would be a multiple of </span><span class="si">#{</span><span class="n">expected</span><span class="si">}</span><span class="s2">&quot;</span>
  <span class="k">end</span>

  <span class="c1"># optionally, override failure message when negated:</span>
  <span class="n">failure_message_when_negated</span> <span class="k">do</span> <span class="o">|</span><span class="n">actual</span><span class="o">|</span>
    <span class="s2">&quot;expected that </span><span class="si">#{</span><span class="n">actual</span><span class="si">}</span><span class="s2"> would not be a multiple of </span><span class="si">#{</span><span class="n">expected</span><span class="si">}</span><span class="s2">&quot;</span>
  <span class="k">end</span>
<span class="k">end</span>
</pre></div>


<p>Example:</p>
<div class="codehilite"><pre><span></span><span class="n">describe</span><span class="p">(</span><span class="mi">9</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_multiple_of</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="p">}</span>

  <span class="c1">#Deliberate failures</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should</span> <span class="n">be_multiple_of</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="p">}</span>
  <span class="n">it</span> <span class="p">{</span> <span class="n">should_not</span> <span class="n">be_multiple_of</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="p">}</span>
<span class="k">end</span>
</pre></div>
</section>
</div>

    </body>
</html>

以上是关于html 服务器规范和rspec的备忘单的主要内容,如果未能解决你的问题,请参考以下文章

ruby 具有期望语法的Rspec Rails备忘单(包括capybara匹配器)

ruby Rails Rspec模型使用rspec-rails,shoulda-matcher,shoulda-callbacks和factory_girl_rails测试骨架和备忘单。差不多

ruby Rails Rspec模型使用rspec-rails,shoulda-matcher,shoulda-callbacks和factory_girl_rails测试骨架和备忘单。差不多

ruby Rails Rspec模型使用rspec-rails,shoulda-matcher,shoulda-callbacks和factory_girl_rails测试骨架和备忘单。差不多

ruby Rails Rspec模型使用rspec-rails,shoulda-matcher,shoulda-callbacks和factory_girl_rails测试骨架和备忘单。差不多

RSpec:特性和请求规范有啥区别?