I would like my node.js tests to ensure that, once the test is over and test.finish() or similar is called, that there is no more code waiting to be run. No more I/O waiting to finish, no more timers waiting to fire, etc. etc.
Is this possible in node.js?
When using nodeunit each test function keeps running until test.done() has been called. Every test function needs to call this. This way you can make sure your callbacks have been executed. I also like to use async module to clean up my code(callbacks) a bit.
Are you using test.expect() at the beginning of each test and test.done() at the end of each one? Think of them like begin and end braces.
I wrote my own, which essentially spins up a node instance for each test. If your test leaves a callback dangling, node just won't exit, and the whole test suite hangs instead of exiting early with success (which would be bad!)
Related
I have a series of tests that are dependent on a step in the middle (such as creating an account). The API that I'm using for this is a kind of brittle (which is a separate problem), and sometimes fails. I'd like to be able to just quit the tests in the middle there when that fails, instead of wait for TestCafe to fail the initial assertions for the next few tests that follow. Is there a way to get the test controller to stop, or signify to the fixture that the tests should stop? I immediately thought of Spock's #Stepwise annotation, but I can't find anything like that in the TestCafe docs.
The Stop on First Fail option stops the entire run once a failed test occurred. If I understand your scenario correctly, you could add an assertion for a successful account creation and if it fails, exit the entire run with this option.
CLI Documentation
API Documentation (under Parameters)
when SetScriptTimeout should be used and please provide me any example.
I know the defn
Sets the amount of time to wait for an asynchronous script to finish execution before throwing an error. If the timeout is negative, then the script will be allowed to run indefinitely.
but not sure what it does exactly.
You've got two answers already, neither of which I find explain clearly the point of setting a script timeout.
First, it is important the script timeout affects only JavaScript code executed with executeAsyncScript and nothing else. In particular, executeScript is not affected by it.
So why do you want to set a timeout for executeAsyncScript? Chandan Nayak correctly explained that the default timeout is 0s so you have to change this timeout if you want to use executeAsyncScript with asynchronous scripts that actually perform some work. But why not just set it to -1 and be done with it? After all, if you set it to -1 then you turn off the timeout. So you won't get any timeouts anymore. Mission accomplished, right? Nope.
What you want to do is set the timeout to a value that allows the code you use with executeAsyncScript to perform it works while at the same time detect when a script has gone rogue. For instance, if from experience you know that a script you pass to executeAsyncScript is going to be done in 2 seconds or less (except perhaps in extremely unusual circumstances), then you set the timeout to 2 seconds so that if there is a bug somewhere and the code never terminates, you get a timeout after 2 seconds. Otherwise, Selenium will happily wait forever for the script to complete.
From WebDriver documentation:
setScriptTimeout(long time, java.util.concurrent.TimeUnit unit)
Sets the amount of time to wait for an asynchronous script to finish execution before throwing an error. This works only for Assync scripts (executeAsyncScript)
Let's run a simple javascript: (Do not set setScriptTimeout ) - Now this shall execute without throwing any issue.
((JavascriptExecutor) driver).executeScript("alert('hello world');");
Lets run a simple Assync Script: ( Do not set setScriptTimeout) - This shall fail with error - "Timed out waiting for async script result after 0ms"
((JavascriptExecutor) driver).executeAsyncScript("window.setTimeout(arguments[arguments.length - 1], 500);");
To resolve the issue: setScriptTimeout to 1 Second:
driver.manage().timeouts().setScriptTimeout(1, TimeUnit.SECONDS);
And then run the same Assync Script mentioned above and it shall execute without any error.
Reason:
The default timeout for a script to be executed is 0ms. In most cases, including the examples below, one must set the script timeout WebDriver.Timeouts.setScriptTimeout(long, java.util.concurrent.TimeUnit) beforehand to a value sufficiently large enough
More Reference Links:
When should setScriptTimeout be used?
WebDriver executeAsyncScript vs executeScript
WebDriver Doc
Web application automation is dependent on many factors like browser, network speed, embedded scripting etc. To write robust code for running in all environments we need to inserts wait for WebElements before performing any operation on that.
WebDriver wait (synchronization) can be obtained either by using support.ui or driver().manage().timeouts()
If we use driver.manage().timeouts(), a common practice to achieve synchronization is to use JavaScript via JavascriptExecutor which in turn provide two methods for script execution:
executeAsyncScript -> This method doesn't block the execution of next line of code...till execution of this method is completed. This method will execute as well as next line of code will be executed...asynchronously. (without blocking each other)
executeScript -> This method will block the execution till it's execution is completed and then it moves to next line of code. In short your automation code will halt till the Javascript is executed via this method.
Now since executeAsyncScript method doesn't block the execution of next line of code, it might be beneficial to use driver.manage().timeouts().setScriptTimeout(30,SECONDS);
so that our code can wait for specified amount of time for an asynchronous script to finish execution before throwing an error.
I have noticed that some Geb functional tests pass with Chrome but fail with PhantomJS, holding all other variables constant. This happens mostly with pages that have some kind of asynchronous activity - one call to $(selector).click() triggers an event handler that updates the DOM, and the DOM updates need to complete before calling $(anotherSelector).click().
I can make the PhantomJS tests pass again by aggressively using waitFor but I don't understand why this would be required with the PhantomJS GhostDriver and not the Chrome driver.
Unfortunately I haven't been able to construct a minimal test case yet isolated from my application.
The only advice I can have is to always make sure that any actions in your tests around asynchronous activities are guarded with waitFor statements. You will avoid problems where one driver is quick enough to finish the asynchronous activity before your test tries to access the new/modified element in your page but other isn't. Not using waitFor around asynchronous activities will also bite you when you start running your tests on CI where they are usually slower and you'll see more failures related to asynchronicity in tested pages.
I also wouldn't consider using waitFor to guard every asynchronous activity in your test as being aggressive. You have to remember that waitFor periodically polls the condition and continues as soon as the condition is fulfilled - so if your browser is quick and the page gets updated before waitFor polls for the first time then you're not penalized speed-wise at all but if it's not then you have a guarantee that there will be a retry to see if the asynch action has finished and the condition was fulfilled. What I find aggressive is using ridiculously high timeouts like 30s where they definitely aren't needed - it just means that if your test fail it will take very long time for it to happen.
I had a recent experience even with IE and Firefox. This is a list you can try:
Of course, waitFor{}/(timeout: ) is your friend
I am pretty sure Chrome and PhantomJS are not behaving exactly the same way. So, manually try and observe what's the difference, then use something like this:
if(System.properties["geb.env"]=="chrome") {
$(selector).click()
} else {
// Do something else
}
Background: My application is used to execute tests using Selenium RC servers, and occasionally I'm running into a problem when my call to a Selenium command doesn't return the response from the RC server - it then ends up blocking the thread that is executing the test.
Sample Code:
Private Delegate Function DoCommand_Delegate(ByVal command As String, ByVal args() As String) As String
...
asyncCommand = New DoCommand_Delegate(AddressOf server.DoCommand)
asyncResult = asyncCommand.BeginInvoke(command, args, Nothing, Nothing)
Try
... (I have it use the AsyncWaitHandle to wait for periods of 10 seconds up to two minutes. At the end of each period it runs some checks for common problems that block Selenium from returning a response (modal dialogs) - I don't think that part is relevant to this question, it's just necessary.)
Finally
result = asyncCommand.EndInvoke(asyncResult)
...
At the time EndInvoke is called, the worker delegate has either already finished or needs to be aborted. Most of the time it already has a response so it works just fine, but on rare occasion Selenium RC's DoCommand doesn't return, so the thread sits there locked.
Finally, my question: is there a resource-friendly way to abort the executing delegate, or do I need to convert it to use a manually controlled thread that can be aborted and disposed?
Note: This is not a question regarding Selenium, just proper multithreading.
Note 2: I've considered doing the following in the Finally before calling EndInvoke:
If Not asyncResult.IsCompleted Then asyncResult.AsyncWaitHandle.Close()
... But I don't know if that would actually work correctly, or what damage that could cause.
There is no way to do the following at the same time:
Abort/kill a thread non-cooperatively
Without destroying all state associated with it (AppDomain/process)
Implies: Either terminate cooperatively (not possible here) or kill the process (AppDomain not enough because native state is involved) or don't kill the thread.
You could just not kill the thread and leave it there hanging. The rest of your program (the remaining tests) can continue to execute.
I'd not be happy to see this in production but for a test suite this could be ok (assuming the hang cannot be fixed).
Why can't a thread be aborted? This has been covered a number of times on Stack Overflow already.
If in my code, I were to call execv, and then I had several lines of code after the call to execv, would those lines get executed, or would they not get executed, since whatever was started by execv replaces the current process?
They wouldn't be executed, unless the execv() call failed. execv() completely replaces the program running in the process that calls it.
They would not get executed, unless you forked the thread and called execv on just one of them.