can i validate 2 conditions inside scalatest eventually block? - scala

I tried to validate 2 conditions inside eventually block... something like this
eventually(timeout(Span(26, Seconds)), interval(Span(2, Seconds))) {
response = executeSomeFunction
response should be = (true)
if (response) {
something = responseResult.get
something should be >= (10)
}
}
What am looking for is eventually should satisfy both the conditions. That is first it should check if response is true and then when response is true, it should validate the condition inside if loop.
I tried executing this but am getting error message
ambiguous reference to overloaded definition" referencing to line
"response should be = (true)"
Am not sure what I am trying to do is even possible inside eventually or not.

The problem is that you write
response should be = (true)
But actually you want to write:
response shouldBe true
In your case you make assignment of response should be: ResultOfBeWordForAny[Boolean] to the value true. Not clear what conversion here you expect.
P.S. Also write response = executeSomeFunction outside of eventually block, otherwise it could be executed multiple times.
P.P.S Moreover you don't need eventual call if you test result of your function, it's anyway in the scope. eventually isn't the best practice and used when function have some async side-effects you would like to test.

Related

Awaiting the same method (passed as a parameter) twice

I'm trying to write a method inside a package I'm currently developing but I got stuck trying to await the same method a second time.
This is the pseudo code for my method:
Future<MyResultClass> ErrorHandlingMethod(Future<MyResultClass> MyMethod) async {
MyResultClass result = await MyMethod;
(if result.failed && result.cause.canBeFixed){
...
...
// Do something that may cause MyMethod to complete successfully
...
...
result = await MyMethod;
}
return result;
}
MyMethod (a DIO request with a bunch of interceptors) completes but the server returns an error code, now in some cases I can fix whatever caused the problem so after doing that I want to make the same call again and return the new result.
The problem is the second time I'm awaiting MyMethod it returns the result I got the first time without making a new DIO request.
The real code is a little more complicated than this but this is the main problem I'm having right now.
Does anyone know how can I force MyMethod to be actually executed again?
Thanks in advance for your help

F# async: parent/child cancellation?

So here we go: given a Confluent.Kafka IConsumer<>, it wraps it into a dedicated async CE and consumes as long as cancellation hasn't been requested. This piece of code is also defends itself against the OperationCancelledException and runs finally block to ensure graceful termination of consumer.
let private consumeUntiCancelled callback (consumer: IConsumer<'key, 'value>) =
async {
let! ct = Async.CancellationToken
try
try
while not ct.IsCancellationRequested do
let consumeResult = consumer.Consume(ct)
if not consumeResult.IsPartitionEOF then do! (callback consumeResult)
with
| :? OperationCanceledException -> return ()
finally
consumer.Close()
consumer.Dispose()
}
Question #1: is this code correct or am I abusing the async?
So far so good. In my app I have to deal with lots of consumers that must die altogether. So, assuming that consumers: seq<Async<unit>> represents them, the following code is what I came up with:
async {
for consumer in consumers do
do! (Async.StartChild consumer |> Async.Ignore).
}
I expect this code to chain childs to the parent's cancellation context, and once it is cancelled, childs gonna be cancelled as well.
Question #2: is my finally block guaranteed to be ran even though child got cancelled?
I have two observations about your code:
Your use of Async.StartChild is correct - all child computations will inherit the same cancellation token and they will all get cancelled when the main token is cancelled.
The async workflow can be cancelled after you call consumer.Consume(ct) and before you call callback. I'm not sure what this means for your specific problem, but if it removes some data from a queue, the data could be lost before it is processed. If that's an issue, then I think you'll need to make callback non-asynchronous, or invoke it differently.
In your consumeUntilCancelled function, you do not explicity need to check while not if ct.IsCancellationRequested is true. The async workflow does this automatically in every do! or let!, so you can replace this with just a while loop.
Here is a minimal stand-alone demo:
let consume s = async {
try
while true do
do! Async.Sleep 1000
printfn "%s did work" s
finally
printfn "%s finalized" s }
let work =
async {
for c in ["A"; "B"; "C"; "D"] do
do! Async.StartChild (consume c) |> Async.Ignore }
Now we create the computation with a cancellation token:
// Run this in F# interactive
let ct = new System.Threading.CancellationTokenSource()
Async.Start(work, ct.Token)
// Run this sometime later
ct.Cancel()
Once you call ct.Cancel, all the finally blocks will be called and all the loops will stop.

Protractor: After completing its task, it Timeouts

I have been trying to automate a case in which i have to create a group of Urls. So after executing the below script all of the groups that are required are added. After completing all of its task , it is throwing timeout error. But the same objects when used in other specs works perfectly.
describe('Test for ToolbarExpandField',function(){
it('Creating a new url group',function(){
emulator.createNewURLGroup(URLGroupName,URLGroupList);
})
})
createNewURLGroup:function(URLGroupName,URLGroupList){
base.click(base.byElement(base.getLocator(emulatorObjects.dropUpBodyOption,['New URL Group'])));
emulatorObjects.uRLGroupNameField.sendKeys(URLGroupName);
browser.waitForAngular();
base.click(emulatorObjects.confirmButton);
expect(base.byElement(base.byCss("option[value = '"+URLGroupName+"']")).getText()).toEqual(URLGroupName);
for(var i = 1; i<URLGroupList.length ; i++){
tsHelper.checkPresence(emulatorObjects.addNewUrlDiv,true);
base.click(emulatorObjects.addNewUrlDiv);
emulatorObjects.urlNameField.sendKeys(URLGroupList[i].name);
emulatorObjects.urlLinkField.sendKeys(URLGroupList[i].link);
base.click(emulatorObjects.saveUrlDetails);
}
tsHelper.checkPresence(emulatorObjects.addNewUrlDiv,false);
base.click(emulatorObjects.confirmButton);// Errors occur here
}
The purpose of testing is to check and test something. So, each test case should have some expectation and it's result. That's why when you used it in some other test cases, it worked, because those test cases must be already having some expectation.
You can add expectation to Creating a new url group test case after calling createNewURLGroup function or if you don't have anything to check, then you can just add expectation which is always true (Not a good way):
Example:
it('Creating a new url group',function(){
emulator.createNewURLGroup(URLGroupName,URLGroupList);
expect(true).toBeTruthy();
})

How to test `Var`s of `scala.rx` with scalatest?

I have a method which connects to a websocket and gets stream messages from some really outside system.
The simplified version is:
def watchOrders(): Var[Option[Order]] = {
val value = Var[Option[Order]](None)
// onMessage( order => value.update(Some(order))
value
}
When I test it (with scalatest), I want to make it connect to the real outside system, and only check the first 4 orders:
test("watchOrders") {
var result = List.empty[Order]
val stream = client.watchOrders()
stream.foreach {
case Some(order) =>
result = depth :: result
if (result.size == 4) { // 1.
assert(orders should ...) // 2.
stream.kill() // 3.
}
case _ =>
}
Thread.sleep(10000) // 4.
}
I have 4 questions:
Is it the right way to check the first 4 orders? there is no take(4) method found in scala.rx
If the assert fails, the test still passes, how to fix it?
Is it the right way to stop the stream?
If the thread doesn't sleep here, the test will pass the code in case Some(order) never runs. Is there a better way to wait?
One approach you might consider to get a List out of a Var is to use the .fold combinator.
The other issue you have is dealing with the asynchronous nature of the data - assuming you really want to talk to this outside real world system in your test code (ie, this is closer to the integration test side of things), you are going to want to look at scalatest's support for async tests and will probably do something like construct a future out of a promise that you can complete when you accumulate the 4 elements in your list.
See: http://www.scalatest.org/user_guide/async_testing

How to properly use spray.io LruCache

I am quite an unexperienced spray/scala developer, I am trying to properly use spray.io LruCache. I am trying to achieve something very simple. I have a kafka consumer, when it reads something from its topic I want it to put the value it reads to cache.
Then in one of the routings I want to read this value, the value is of type string, what I have at the moment looks as follows:
object MyCache {
val cache: Cache[String] = LruCache(
maxCapacity = 10000,
initialCapacity = 100,
timeToLive = Duration.Inf,
timeToIdle = Duration(24, TimeUnit.HOURS)
)
}
to put something into cache i use following code:
def message() = Future { new String(singleMessage.message()) }
MyCache.cache(key, message)
Then in one of the routings I am trying to get something from the cache:
val res = MyCache.cache.get(keyHash)
The problem is the type of res is Option[Future[String]], it is quite hard and ugly to access the real value in this case. Could someone please tell me how I can simplify my code to make it better and more readable ?
Thanks in advance.
Don't try to get the value out of the Future. Instead call map on the Future to arrange for work to be done on the value when the Future is completed, and then complete the request with that result (which is itself a Future). It should look something like this:
path("foo") {
complete(MyCache.cache.get(keyHash) map (optMsg => ...))
}
Also, if singleMessage.message does not do I/O or otherwise block, then rather than creating the Future like you are
Future { new String(singleMessage.message) }
it would be more efficient to do it like so:
Future.successful(new String(singleMessage.message))
The latter just creates an already completed Future, bypassing the use of an ExecutionContext to evaluate the function.
If singleMessage.message does do I/O, then ideally you would do that I/O with some library (like Spray client, if it's an HTTP request) that returns a Future (rather than using Future { ... } to create another thread which will block).