venmo / dvr Goto Github PK
View Code? Open in Web Editor NEWNetwork testing for Swift
Home Page: http://blog.soff.es/network-testing-in-swift-with-dvr
License: MIT License
Network testing for Swift
Home Page: http://blog.soff.es/network-testing-in-swift-with-dvr
License: MIT License
Hi there,
I'm using DVR, and so far I've managed successfully to create tests when api requests return success. But now I want to test the failure of the same requests. So I'm facing a problem when using DVR to test failures (401, 404 etc)..
When run for 2nd time (first time is to record the response), instead of failure callback, success callback is called with the error response inside of it. Any idea why?
Using Alamofire.
Example code (creating and executing any request):
request.validate().responseJSON(completionHandler: {
response in
switch response.result {
case .success(let JSON):
// This is what gets called instead of failure. Response code is 401 and the JSON contains error message.
callback(true, JSON, nil)
case .failure(let error):
if let data = response.data, data.count > 0 {
let JSON = try! JSONSerialization.jsonObject(with: data, options: .allowFragments)
callback(false, JSON, error as NSError?)
} else {
callback(false, nil, error as NSError?)
}
}
}).resume()
I intentionally changed the cassette name when initialising a session, however the test fails with fatalError()
call from DVR stating that the request was not found. I am certain the json file is not there and have performed the clean build/test and even removal of DerivedData
folder.
DownloadTask crashes with message "[DVR] Something has gone horribly wrong." when trying to download a file from a remote location.
I am getting the same message even when i am using the example test for downloadTask.
The url is valid and the file is there because i download with the sharedSession the file from that URL, and it downloads successfully.
Right now, our README is fairly sparse. It might be good to pull out some examples from our tests cases and document how DVR can be used in those situations.
When you use sandbox and production services they have different baseURL. I added the possibility to ignore the baseURL when matching url requests. If this is useful i can create a PR from my fork.
Both my Xcode's (7.1 and 7.2-beta.3) crash when I run a test that uses DVR where no cassette exists yet. Crash happens right after DVR records the request, logs the fact to console and then aborts to stop running - immediately after or maybe even at the time of the abort there's a crash.
Here's a snippet from the crash log:
Crashed Thread: 38 <DBGLLDBSessionThread (pid=2221)> Dispatch queue: DVTInvalidationPreventionQueue
DVR is probably not at fault here, but has anyone experienced this and been able to fix or workaround the crash?
Sometimes, it would be nice if you could ignore the body or say the headers matter or just some headers.
Seems to be a new issue in 0.2.0. I get either Invalid request. The request was not found in the cassette.
or Something has gone horribly wrong.
before Xcode hits a breakpoint and promptly crashes.
Unable to build project in Xcode 11 beta 6.
I receive error Instance method 'filter' is internal and cannot be referenced from a default argument value
in Session class init(outputDirectory:cassetteName:testBundle:backingSession:)
function.
testBundle
.Hello,
while using the library I faced that cassettes may contain sensitive information (e.g., API keys that are passed with GET request - domain.com?apiKey=XXX
) which:
Thus, I'd like to add support parametersToIgnore
for the Session, so later it could be used for interaction comparison and for removing parameters from the cassette.
Could you confirm if that would be accepted and if that's the case whether the suggested approach makes sense?
And thank you for the nice library, it's very useful for network layer testing.
This will require refactoring a significant amount. Right now most of the recording logic lives in the data task. We'll need to make this more abstract so it can work for both.
We could also make download tasks use data tasks internally and just write it out to a temp file. The consumer won't know the difference.
Hey there,
love the idea of the library but I just cannot get it record anything. What am I missing? Tried injecting the session all the way to where it was used which didn't do anything so I took a step back and just tried recording the session directly. Which again didn't do anything:
let session = Session(cassetteName: "example")
let task = session.dataTaskWithURL(NSURL(string: "https://api.dailymotion.com/video/x26m1j4")!) { _, _, _ in
}
task.resume()
Also tried dataTaskWithRequest
but same difference. The test always passes.
Looking at the README I would expect it to fail with assert: "โฆ with path of the recorded file. โฆ"
Put together a sample: https://github.com/JanGorman/DVRSample
Right now, we don't check them at all. It would be cool if you could opt-in to that.
Just upgraded to DVR v0.1 and migrated my JSON cassettes using the convert.rb script. Tests started failing because I was not getting JSON data (just a response).
I believe the culprit is https://github.com/venmo/DVR/blob/master/DVR/Interaction.swift#L58.
DVR checks for contentType == "application/json"
, but the Content-Type header field can contain more than that. In my case it is application/json; charset=utf-8
.
Was gonna submit a pull request, but the project refuses to run tests for me due to some Xcode 7 beta 5 silliness: seeing dozens of devices in my device list, then when I choose one and try to run tests from test navigator it says the device is not valid for tests. Building for tests leads to symbol not found errors. :\
One more thing: thank you for DVR. Really liking how it makes a whole category of tests in my app feasible. ๐
So this is a bug that has been haunting me for a few weeks now. And was the cause of me not running my service classes' specs unless I wasn't too lazy to recreate the cassettes.
Here's a snippet from my project that creates a get request with query parameters:
if let p = params where method == "GET" {
let charset = NSCharacterSet.URLQueryAllowedCharacterSet()
var query = ""
for key,value in p {
if let escapedValue = String(p[key]!).stringByAddingPercentEncodingWithAllowedCharacters(charset) {
query += "\(key)=\(escapedValue)&"
}
}
urlString += "?\(query)"
}
param
is a [String : AnyObject]
dictionary;method
is a string defining http verbSo this snippet constructs a query string and appends it to urlString
variable that has the base url and resource path combined.
This urlString
is then passed to NSURLRequest
initializer that creates a request to perform with a session that holds a cassette.
And this is where the trouble comes in. DVR check's for presence of interaction in the cassette by looking at the request's URL. And by definition dictionary does not guarantee the order of the keys in which they will be passed in iteration.
If you have ["foo": 5, "bar" : true]
the resulting query string can have two variations:
let query1 = "foo=5&bar=true&"
let query2 = "bar=true&foo=5&"
In the end they mean the same thing and will be interpreted correctly by the server, but the check will fail since query1 != query2
.
I'm not sure how people construct requests in their code, but the solution can be achieved in two ways
?
) and compare the key values that are stored in the query string (reconstruct the dict by splitting by &
and then by =
).If this project is still alive, I'd like to hear anyones thoughts.
Any chance a new release can be pushed to the Cocoapod's specs repo so that a Swift 4.2 version is available?
I'm adding a podspec for DVR, but it requires a license. I'm assuming MIT, but can you please add it to the repo?
I was thinking having startRecording
/stopRecording
in a test is weird since you only record once. Those methods are used for batch requests in one cassette. It would probably be best if these were renamed to beginBatch
and finishBatch
(or endBatch
).
I can't install 2.0.0 with pod install
because it's not in the pods repo. Still stuck on 1.3.2
My type used for storing errors returned by my API hold the http status code so that user's can get more information while debugging their failed requests. However, when writing acceptance tests that the correct status codes are returned, DVR simply returns HTTP status code 0 always.
It looks like the status code is not being recorded in the cassette.
Any chance we can also record the status code?
Unfortunately I have not been able to pinpoint the issue yet (I have taken a look at the changes from 1.2.0
to 1.3.0
) but I can share that I have a branch where all my tests correctly find the relevant cassettes on version 1.2.0
(and Xcode 9), but with 1.3.0
(and Xcode 10) the tests crash as the cassettes can't be found.
Something about the diff between 1.2.0
and 1.3.0
is causing this change. Any ideas what may be the issue?
If we can't pinpoint the problem, then maybe we should deprecate 1.3.0
and release it as 2.0.0
instead since the changes are seemingly breaking behavior.
Since Cassette
saves an array of Interaction
s, instead of just one, it would be great to add support for recording and replaying multiple interactions in one test case.
Possible changes for recording:
Session
called recordMultiple
, which would allow for not stopping after the first Interaction
has been recordedSession
called finishRecording()
, which persists all Interaction
s from memory to disk and asserts to present the file path, like it does now. finishRecording()
would only have to be called if recordMultiple
is set to true
finishRecording()
from deinit
of Session
, so that user doesn't have to call it manuallyPossible changes for replaying:
Interaction
should be played next, automatically increment after each replaydeinit
that exactly the number of prerecorded Interaction
s has been called (fail the test if more or less network calls were made)???
Profit.
When using Xcode 11 and Swift 5.1 a dataTask
called with an URL
as parameter (instead of an URLRequest
) results in an NSInvalidArgumentException
:
[Session defaultTaskGroup]: unrecognized selector sent to instance
I'm trying to use a DVR Session
with Alamofire but using it to initialize a Manager
generates an unrecognized selector
exception.
This conversation deals with my use case, but the advice ("Just create a session delegate, then create your custom session, and pass both in.") doesn't seem to work. Since DVR's Session
is a subclass of NSURLSession
I would expect that you could ask for its delegate
but it's breaking for some reason.
let delegate = Manager.SessionDelegate()
let backingSession = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: delegate, delegateQueue: nil)
let maybeBundle = NSBundle.allBundles().filter{ $0.bundlePath.lowercaseString.containsString("xctest") }.first
if let bundle = maybeBundle {
let session = Session(outputDirectory: "~/Desktop/DVR/", cassetteName: cassetteName, testBundle: bundle, backingSession: backingSession)
}
I know VCR does this. We should copy them. Manually redacting cassettes is pretty tedious.
If you specify a cassette, it exists, and doesn't contain the request you specified, it would be really helpful if it said why it thinks the request you specified doesn't match the one in the cassette.
Please add a support for the tv os.
This is because json encodes and decodes parameters in a non-deterministic order. This causes tests to fail.
Therefore we cannot directly compare HTTPBody
's like we do here:
https://github.com/venmo/DVR/blob/master/DVR/Cassette.swift#L17
I'm writing an API wrapper as a library and just started using DVR in my tests, loving it! I'd really love my library staying compatible with Cocoapods, Carthage and Swift Package Manager. This world of three different package managers to support is really something in this ecosystem ๐. My dependencies are declared and integrated via Carthage, which works just fine. Cocoapods doesn't really need to know about DVR since that never runs my tests anyhow. Buuut I kinda still want to be able to run swift test
... Is there any way to currently accomplish this?
I don't think SPM supports private/dev/test dependencies, does it? Or would it make sense to include DVR as a normal dependency but only require it in test files? Not sure how Swift handles that...
Nevertheless, support for SPM here would be superb and much appreciated. If it makes sense of course. Thanks! ๐
Created a fork, seems to load fine once updated.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.