#!/usr/bin/env ruby require 'soaspec' require 'fileutils' def create_file(options) filename = options[:filename] raise 'Need to pass filename' unless filename content = options[:content] raise 'Need to pass contents to insert into file' unless content if File.exist? filename old_content = File.read(filename) if old_content != content warn "!! #{filename} already exists and differs from template" end else File.open(filename, 'w') do |f| f.puts content end puts 'Created: ' + filename end end def create_folder(folder) if File.exists? folder unless File.directory? folder $stderr.puts "!! #{folder} already exists and is not a directory" end else FileUtils.mkdir folder puts "Created folder: #{folder}/" end end puts 'Creating files for soaspec' gem_content = <<-EOF source 'https://rubygems.org' gem 'data_magic' gem 'require_all' gem 'rspec_junit_formatter' gem 'rake' gem 'soaspec' EOF rake_content = <<-EOF # The list of task for a Rake file can be seen with `rake -T` require 'rspec/core/rake_task' # See See https://relishapp.com/rspec/rspec-core/docs/command-line/rake-task for details # This runs `rspec` command with the following options. Type `rake spec` to run this task RSpec::Core::RakeTask.new(:spec) do |t, task_args| t.pattern = "spec/*_spec.rb" # Run all specs in 'spec' folder ending in '_spec' # Next line shows output on the screen, Junit xml report and an HTML report t.rspec_opts = "--format documentation --format RspecJunitFormatter --out logs/spec.xml --format html --out logs/spec.html" t.fail_on_error = false end task :default => :spec # This runs the 'spec' task by default when no task is mentioned. E.g., if only `rake` is typed EOF spec_helper_content = <<-EOF require 'soaspec' require 'require_all' require_all 'lib' require 'data_magic' include DataMagic # Used as example of loading data smartly. Use 'data_for' method to load yml data RSpec.configure do |config| # This will make backtrace much shorter by removing many lines from rspec failure message config.backtrace_exclusion_patterns = [ /rspec/ ] end EOF weather_web_service = <<-EOF require 'soaspec' # This class is not part of the gem. It's an example of a class you can make # to describe your APIs. Usually this would exist in the 'lib' directory # Common configuration for the Savon client should go here class WeatherWebService < Soaspec::BasicSoapHandler # Add to or override default Savon client options def savon_options { wsdl: 'http://www.webservicex.com/globalweather.asmx?wsdl', convert_request_keys_to: :camelcase } end # Specifying that get_weather_result must be present in the SOAP response def mandatory_elements [:get_weather_result] end # Example of xpath value that must be true for all success scenarios def mandatory_xpath_values { '//xmlns:GetWeatherResult' => 'Data Not Found' } end # Example of setting an attribute on the root XML element def root_attributes { 'Version' => '1' } end end EOF soap_spec_content = <<-EOF require 'spec_helper' Soaspec::Environment.strip_namespaces = true # This allows namespace not to be used. Be careful with this soap_example = WeatherWebService.new('Get Weather') soap_example.operation = :get_weather soap_example.default_hash = { city_name: 'Sydney', country_name: 'Australia' } # soap_example.template_name = 'soap_template' # Use this if you'd rather use template file and comment out previous line context soap_example do describe Exchange.new(:default) do it { is_expected.to contain_value 'Data Not Found' } it_behaves_like 'success scenario' end describe Exchange.new(:china, city_name: 'Shanghai', country_name: 'China') do it_behaves_like 'success scenario' context 'handle xpath' do its(['GetWeatherResult']) { is_expected.to eq 'Data Not Found' } # Don't need to use namespace it { is_expected.to have_element_at_xpath '//xmlns:GetWeatherResult' } it { is_expected.to have_xpath_value '//xmlns:GetWeatherResult' => 'Data Not Found' } end end describe Exchange.new(:japan, data_for(:japan)) do it_behaves_like 'success scenario' its(['//xmlns:GetWeatherResult']) { is_expected.to eq 'Data Not Found' } # Can specify namespace if wanted end end soap_example.default_hash = { city_name: 'Washington' } context 'error scenarios' do context soap_example do describe Exchange.new(:error) do it_behaves_like 'error scenario' end end end EOF shared_examples_content = <<-EOF require 'rspec' shared_examples_for 'error scenario' do it 'does not have status code of 200' do expect(described_class.status_code).not_to eq 200 end end EOF soap_template_content = <<-EOF <%= test_values[:city_name] || 'Wellington' %> <%= test_values[:country] || 'New Zealand' %> EOF default_yaml_content = <<-EOF japan: city_name: 'Tokyo' country_name: 'Japan' EOF readme_content = <<-EOF # Prerequisites This creates files within an existing folder. It could add onto an existing project. For a new project create a folder and be at it's location on the command line ``` mkdir soaspec_test cd soaspec_test ``` Run `bundle install` to install the gems mentioned in the Gemfile. To avoid conflict with gems on the machine globally it may be better to specify gem location with: `bundle install --path ~/.gem` # Running tests On the command line type: `bundle exec rake spec` or simply `bundle exec rake` # Structure ## Tests Tests are within the 'spec' folder and end in '_spec'. Setup and teardown for tests is in 'spec/spec_helper' ## Templates These are the base requests with ERB inside them to create smartly changing requests accoring to the test.yml ## Libaries Libaries to be installed are in 'Gemfile'. Specific gem versions can be specified here and enforeced with `bundle exec rake` ## Reports Reports are shown in the 'logs' folder. By default Rake produces a junit, an html report, and a traffic.log file with the API request and responses in it EOF create_file(filename: 'Gemfile', content: gem_content) create_file(filename: 'Rakefile', content: rake_content) create_file(filename: 'README.md', content: readme_content) create_folder 'lib' create_file(filename: 'lib/weather_web_service.rb', content: weather_web_service) create_file filename: 'lib/shared_example.rb', content: shared_examples_content create_folder 'config' create_folder 'config/data' create_file(filename: 'config/data/default.yml', content: default_yaml_content) create_folder 'spec' create_file(filename: 'spec/spec_helper.rb', content: spec_helper_content) create_file(filename: 'spec/soap_spec.rb', content: soap_spec_content) create_folder 'template' create_file(filename: 'template/soap_template.xml', content: soap_template_content) create_folder 'logs' puts "Run 'bundle install' to install necessary gems" puts "Run 'rake spec' to run the tests"