I am trying to integrate SEOMOZ API with VCR.
As the API request to SEOMOZ contains parameters that change for the same request over time, I need to implement a custom matcher.
Here is what my API call looks like :
http://lsapi.seomoz.com/linkscape/url-metrics/#{self.url}?Cols=#{cols}&AccessID=#{moz_id}&Expires=#{expires}&Signature=#{url_safe_signature}
I also make calls to other endpoints such as Twitter,Facebook etc etc. For which the default matcher does the job well.
How can I override the matcher behavior just for SEOMOZ. Also on what parameters should I best match the request in this case.
You'll want to match on all parameters except Signature and Expires.
Another option you might consider (we use it internally when using VCR with this sort of API) is to record the time of the test in a file with the cassettes, and use Timecop or something equivalent to ensure you're re-running the recorded test at the "same time" every time you run it.
You can use the VCR.request_matchers.uri_without_params custom matcher, see https://relishapp.com/vcr/vcr/v/2-5-0/docs/request-matching/uri-without-param-s
You would use it like this in your case:
VCR.configure do |c|
# ...
c.default_cassette_options = {
# ...
# the default is: match_requests_on: [:method :uri]
match_requests_on: [:method, VCR.request_matchers.uri_without_params(:Signature, :Expires)]
}
end
Related
I am writing a REST API GET endpoint that needs to both return a response and store records to either GCP Cloud SQL (MySQL), but I want the return to not be dependent on completion of the writing of the records. Basically, my code will look like:
def predict():
req = request.json.get("instances")
resp = make_response(req)
write_to_bq(req)
write_to_bq(resp)
return resp
Is there any easy way to do this with Cloud SQL Client Library or something?
Turns our flask has a functionality that does what I require:
#app.route("predict", method=["GET"]):
def predict():
# do some stuff with the request.json object
return jsonify(response)
#app.after_request
def after_request_func(response):
# do anything you want that relies on context of predict()
#response.call_on_close
def persist():
# this will happen after response is sent,
# so even if this function fails, the predict()
# will still get it's response out
write_to_db()
return response
One important thing is that a method tagged with after_request must take an argument and return something of type flask.Response. Also I think if method has call_on_close tag, you cannot access from context of main method, so you need to define anything you want to use from the main method inside the after_request tagged method but outside (above) the call_on_close method.
In my Ruby on Rails application there are 2 Localhost servers running. I am writing test cases for the 1st server and so I have to mock the 2nd server.
For this I am using VCR to record the responses I get from the 2nd server and play the recorded cassette while running the tests on the 1st server.
I am stuck at the part where the 1st server makes a request to 2nd server(the session_id in the URL changes each time) and I want the response to be same every time it makes a request.
Using VCR you can match requests on any parameters you wish (method, host, path, etc...) using the match_requests_on cassette option or a fully custom matcher - https://relishapp.com/vcr/vcr/v/3-0-3/docs/request-matching
I made this work via params ignoring. So for you something like this could work:
VCR.use_cassette('name_of_your_cassette', match_requests_on: [:method, VCR.request_matchers.uri_without_params('session_id')]) do
# here is your http query
end
In my case it was query that was changing so I ignored that in vcr request matcher.
For eg, I save paths.json and add the following. I know there is a mistake in the way i try, but not able to find it
{
"name": "JSON Path's",
"description": "This mainly store the paths of the JSON elements which are validated in each scenario",
"SC_4": {
"appHeader": "$.testResponse.applicationHeader",
"ProductsAction": "$.testResponse.applicationHeader.item.action"
}
}
* def attributes = read('../jsonpaths/paths.json')
Given url endPointURL
And request baseJsonRequest
When method post
Then status 200
* def appHeaderSecondTry = attributes.SC_4.appHeader
* print appHeaderSecondTry
Wow you are getting to be a power user of Karate so soon :P
Okay, personally I don't recommend trying to build a mini-framework over Karate like you are doing, I can see what you are trying to do - keep all assertions "declarative" and try to re-use common code for the actual HTTP call etc.
My opinionated take on this is, you save very few lines of code (because of how easy it is to make an HTTP request in Karate). Also, you should be able to re-use a feature file via the call keyword. I would urge you to try and keep the match statements "normal" in your tests.
That said, what you are missing is the karate.eval() operation, look for it in the doc. Here is an example (line 91): js-arrays.feature
I'm willing to use 2 variables for random values with the same request.
I defined both in User Parameters as follows: var1=${__Random(1,100)}; var2=${__Random(1000,2000)} (Also I checked: Update once per iteration)
I have the requests:
Request1: GET user/${var1}
Request2: GET user/${var2}
During run-time, when it gets to request2 var2 equals var1!
How do I fix that?
Well, User Parameters is a PreProcessor so you should put it as a child of your HTTP Request in order to get correct behavior. You can use Debug Sampler and View Results Tree listener combination to validate variables values (see How to Debug your Apache JMeter Script article for more details)
I would recommend discarding this User Parameters and injecting the __Random() function directly into your HTTP Request sampler Path like
/user/${__Random(1,100,var1)}
/user/${__Random(1000,2000,var2)}
This is a simpler way to generate random numbers and get them stored into JMeter Variables.
I have a Rails 3 background job (delayed_job) which sends a hipchat / Campfire message to their API and I want to check the response in my Cucumber feature. Is there a way to get the last HTTP response(s) which VCR have recorded?
The feature looks like this
#vcr
Scenario: Send hipchat message when task created
Given an hipchat_sample integration exists with app: app "teamway"
When I create an "ActionMailer::Error" task to "Teamway"
And all jobs are worked off # invoke Delayed::Worker.new.work_off
Then a hipchat message should be sent "ActionMailer::Error"
In my step definition I want to check the response body:
Then /^a hipchat message should be sent "(.*?)"$/ do |arg1|
# Like this:
# VCR::Response.body.should == arg1
end
VCR already records the request and response, but I do not know how to take them. I think of something similar to catching the emails sent with Pickle's steps. Does anybody have an idea how to do this?
I use rails 3.2.8, cucumber-rails 1.3 and vcr 2.2.4 (with webmock).
Best regards
Torsten
You can use VCR.current_cassette to get the current cassette, and then interrogate that to get the [VCR::HTTPInteraction][1] object you're looking for, but it'll be a bit complex--the VCR cassette stores the newly recorded HTTP interactions separately from the ones it has available for playback and from the ones it has already played back...so you'll need some complex conditionals to ensure things work properly both when your tests are recording and when they are playing back.
Instead, I recommend you use an after_http_request hook:
module HipmunkHelpers
extend self
attr_accessor :last_http_response
end
Before { HipmunkHelpers.last_http_response = nil }
VCR.configure do |c|
c.after_http_request(lambda { |req| URI(req.uri).host == 'hipmunk.com' }) do |request, response|
HipmunkHelpers.last_http_response = response
end
end
Then, in your cucumber step, you can access HipmunkHelpers.last_http_response.
For more details on the after_http_request hook, check out the relish docs.