module Soaspec # Help with tasks common to soaspec executables module ExeHelpers require 'fileutils' # @param [String] filename Name of the file to create # @param [String] content Content to place inside file def create_file(filename: nil, content: nil, ignore_if_present: false) #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 && !ignore_if_present warn "!! #{filename} already exists and differs from template" end else File.open(filename, 'w') { |f| f.puts content } puts 'Created: ' + filename end end def create_folder(folder) if File.exist? folder unless File.directory? folder warn "!! #{folder} already exists and is not a directory" end else FileUtils.mkdir folder puts "Created folder: #{folder}/" end end def rake_content <<-RAKE # 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| 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 RAKE end def rake_virtual_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(:run_spec) do |t| 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 :spec => %w[start_test_server run_spec] task :default => :spec # This runs the 'spec' task by default when no task is mentioned. E.g., if only `rake` is typed desc 'Start virtual web service' task :start_test_server do ENV['test_server_pid'] = Process.spawn('ruby', 'spec/test_server.rb', err: %w[logs/test_server.log w]).to_s puts 'Running test server at pid ' + ENV['test_server_pid'] end EOF end def gem_content <<-EOF source 'https://rubygems.org' gem 'data_magic' gem 'require_all' gem 'rspec_junit_formatter' gem 'rake' gem 'soaspec' gem 'sinatra' EOF end def 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/ ] # Close test server after all RSpec tests have run config.after(:suite) do Process.kill(:QUIT, ENV['test_server_pid'].to_i) if ENV['test_server_pid'] # && Process.wait - causes failure end end EOF end # @return [String] Content of README.md to aid someone getting started with this using this gem def readme_content <<-EOF # Installation 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 ## Data Data used in the test is stored in `config/data` folder. The `data_magic` gem is used by default to read files here. ## 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 end def test_server_content <<-FILEEOF # Used to run virtual web service on localhost. This makes tests more reliable and faster require 'sinatra' require 'nokogiri' require 'erb' # Representing a GetBank SOAP service class GetBank def self.success_response_template <<-EOF Deutsche Bank DEUTDEMMXXX <%= soap_action %> München <%= @test_id %> EOF end def self.error_response_template <<-EOF soapenv:Receiver org.apache.axis2.databinding.ADBException: Unexpected subelement getBank org.apache.axis2.AxisFault: org.apache.axis2.databinding.ADBException: Unexpected subelement getBank at org.apache.axis2.AxisFault.makeFault(AxisFault.java:417) at com.thomas_bayer.blz.BLZServiceMessageReceiverInOut.fromOM(BLZServiceMessageReceiverInOut.java:124) at com.thomas_bayer.blz.BLZServiceMessageReceiverInOut.invokeBusinessLogic(BLZServiceMessageReceiverInOut.java:43) at org.apache.axis2.receivers.AbstractInOutSyncMessageReceiver.invokeBusinessLogic(AbstractInOutSyncMessageReceiver.java:42) at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:96) at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:145) at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:275) at org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:120) at javax.servlet.http.HttpServlet.service(HttpServlet.java:646) at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.Exception: org.apache.axis2.databinding.ADBException: Unexpected subelement getBank at com.thomas_bayer.adb.GetBankType$Factory.parse(GetBankType.java:423) at com.thomas_bayer.adb.GetBank$Factory.parse(GetBank.java:304) at com.thomas_bayer.blz.BLZServiceMessageReceiverInOut.fromOM(BLZServiceMessageReceiverInOut.java:117) ... 25 more Caused by: org.apache.axis2.databinding.ADBException: Unexpected subelement getBank at com.thomas_bayer.adb.GetBankType$Factory.parse(GetBankType.java:410) ... 27 more EOF end def self.response_for(request) request_body = request.body soap_action = request.env['HTTP_SOAPACTION'].strip doc = Nokogiri::XML(request_body) blz_element = doc.xpath('//tns:blz').first return 500, error_response_template unless blz_element @test_id = blz_element.inner_text ERB.new(success_response_template).result(binding) end end # This is the one being hit post '/BLZService' do GetBank.response_for request end FILEEOF end end end