
Infrastructure Behavior Testing Framework.
First, create Gemfile:
source 'https://rubygems.org'
gem 'infrataster'Install gems:
$ bundle install
Install Vagrant: Official Docs
Create Vagrantfile:
# Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "hashicorp/precise64"
config.vm.define :proxy do |c|
c.vm.network "private_network", ip: "192.168.33.10"
c.vm.network "private_network", ip: "172.16.33.10", virtualbox__intnet: "infrataster-example"
end
config.vm.define :app do |c|
c.vm.network "private_network", ip: "172.16.33.11", virtualbox__intnet: "infrataster-example"
end
endStart VMs:
$ vagrant up
Initialize rspec directory:
$ rspec --init
create spec/spec_helper.rb
create .rspec
require 'infrataster/rspec' and define target servers for testing in spec/spec_helper.rb:
# spec/spec_helper.rb
require 'infrataster/rspec'
Infrataster::Server.define(
:proxy, # name
'192.168.0.0/16', # ip address
vagrant: true # for vagrant VM
)
Infrataster::Server.define(
:app, # name
'172.16.0.0/16', # ip address
vagrant: true, # for vagrant VM
from: :proxy # access to this machine via SSH port forwarding from proxy
)
# Code generated by `rspec --init` is following...Or
# spec/spec_helper.rb
require 'infrataster/rspec'
Infrataster::Server.define(:proxy) do |server|
server.address = '192.168.0.0/16'
server.vagrant = true
end
Infrataster::Server.define(:app) do |server|
server.address = '172.16.0.0/16'
server.vagrant = true
server.from = :proxy
end
# Code generated by `rspec --init` is following...Then, you can write spec files:
# spec/example_spec.rb
require 'spec_helper'
describe server(:app) do
describe http('http://app') do
it "responds content including 'Hello Sinatra'" do
expect(response.body).to include('Hello Sinatra')
end
it "responds as 'text/html'" do
expect(response.headers['content-type']).to eq("text/html")
end
end
endRun tests:
$ bundle exec rspec
2 examples, 2 failures
Currently, the tests failed because the VM doesn't respond to HTTP request.
It's time to write provisioning instruction like Chef's cookbooks or Puppet's manifests!
"Server" is a server you tests. This supports Vagrant, which is very useful to run servers for testing. Of course, you can test real servers.
You should define servers in spec_helper.rb like the following:
Infrataster::Server.define(
# Name of the server, this will be used in the spec files.
:proxy,
# IP address of the server
'192.168.0.0/16',
# If the server is provided by vagrant and this option is true,
# SSH configuration to connect to this server is got from `vagrant ssh-config` command automatically.
vagrant: true,
)
Infrataster::Server.define(
# Name of the server, this will be used in the spec files.
:app,
# IP address of the server
'172.16.0.0/16',
# If the server is provided by vagrant and this option is true,
# SSH configuration to connect to this server is got from `vagrant ssh-config` command automatically.
vagrant: true,
# Which gateway is used to connect to this server by SSH port forwarding?
from: :proxy,
# options for resources
mysql: {user: 'app', password: 'app'},
)You can specify SSH configuration manually too:
Infrataster::Server.define(
# ...
ssh: {host_name: 'hostname', user: 'testuser', keys: ['/path/to/id_rsa']}
)Infrataster has "fuzzy IP address" feature. You can pass IP address which has netmask (= CIDR) to Infrataster::Server#define. This needs vagrant option or ssh option which has host_name because this fetches all IP address via SSH and find the matching one.
Infrataster::Server.define(
:app,
# find IP address matching 172.16.0.0 ~ 172.16.255.255
'172.16.0.0/16',
)Of course, you can set fully-specified IP address too.
Infrataster::Server.define(
:app,
'172.16.11.22',
# or
'172.16.11.22/32',
)You can execute a command on the server like the following:
describe server(:proxy) do
let(:time) { Time.now }
before do
current_server.ssh_exec "echo 'Hello' > /tmp/test-#{time.to_i}"
end
it "executes a command on the current server" do
result = current_server.ssh_exec("cat /tmp/test-#{time.to_i}")
expect(result.chomp).to eq('Hello')
end
endThis is useful to test cases which depends on the status of the server.
"Resource" is what you test by Infrataster. For instance, the following code describes http resource.
describe server(:app) do
describe http('http://example.com') do
it "responds content including 'Hello Sinatra'" do
expect(response.body).to include('Hello Sinatra')
end
end
endhttp resource tests HTTP response when sending HTTP request.
It accepts method, params and header as options.
describe server(:app) do
describe http(
'http://app.example.com',
method: :post,
params: {'foo' => 'bar'},
headers: {'USER' => 'VALUE'}
) do
it "responds with content including 'app'" do
expect(response.body).to include('app')
# `response` is a instance of `Faraday::Response`
# See: https://github.com/lostisland/faraday/blob/master/lib/faraday/response.rb
end
end
# Gzip support
describe http('http://app.example.com/gzipped') do
it "responds with content deflated by gzip" do
expect(response.headers['content-encoding']).to eq('gzip')
end
end
describe http('http://app.example.com/gzipped', inflate_gzip: true) do
it "responds with content inflated automatically" do
expect(response.headers['content-encoding']).to be_nil
expect(response.body).to eq('plain text')
end
end
# Redirects
describe http('http://app.example.com/redirect', follow_redirects: true) do
it "follows redirects" do
expect(response.status).to eq(200)
end
end
# Custom Faraday middleware
describe http('http://app.example.com', faraday_middlewares: [
YourMiddleware,
[YourMiddleware, options]
]) do
it "uses the middlewares" do
expect(response.status).to eq(200)
end
end
endcapybara resource tests your web application by simulating real user's interaction.
describe server(:app) do
describe capybara('http://app.example.com') do
it 'shows food list' do
visit '/'
click_link 'Foods'
expect(page).to have_content 'Yummy Soup'
end
end
endmysql_query resource is now in infrataster-plugin-mysql.
pgsql_query resource sends a query to PostgreSQL server.
pgsql_query is provided by infrataster-plugin-pgsql by @SnehaM.
dns resource sends a query to DNS server.
dns is provided by infrataster-plugin-dns by @otahi.
memcached resource sends a query to memcached server.
memcached is provided by infrataster-plugin-memecached by @rahulkhengare.
redis resource sends a query to redis server.
redis is provided by infrataster-plugin-redis by @rahulkhengare.
firewall resource tests your firewalls.
firewall is provided by infrataster-plugin-firewall by @otahi.
Unit tests are under spec/unit directory.
$ bundle exec rake spec:unit
Integration tests are under spec/integration directory.
$ bundle exec rake spec:integration:prepare
$ bundle exec rake spec:integration
- https://speakerdeck.com/ryotarai/infrataster-infra-behavior-testing-framework-number-oedo04
- Infratasterでリバースプロキシのテストをする
- Google-Translated: Testing reverse proxy with Infrataster
- Fork it ( http://github.com/ryotarai/infrataster/fork )
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request

