I have a XCTestCase that is writing some asset that I would like to clean if it success. I discover that there is a static tearDown() method that I can override which is executed at the end of the test case. How can I know if the test case succeeded or not?
XCTestObserver is now deprecated so you should use the XCTestObservationCenter.
You should implement an observer that conforms to XCTtestObservation.
XCTestObservationCenter.sharedTestObservationCenter().addTestObserver(observer)
Apple's staff quote in XCTestObservation.swift:
Hooks for being notified about progress during a test run.
You can find how to handle testCaseDidFinish in Print Observer
func testCaseDidFinish(_ testCase: XCTestCase) {
let testRun = testCase.testRun!
let verb = testRun.hasSucceeded ? "passed" : "failed"
// FIXME: Apple XCTest does not print a period after "(N seconds)".
// The trailing period here should be removed and the functional
// test suite should be updated.
printAndFlush("Test Case '\(testCase.name)' \(verb) (\(formatTimeInterval(testRun.totalDuration)) seconds).")
}
XCTest has a property, testRun, which returns the XCTestRun for your test, which has a hasSucceeded property.
http://masilotti.com/xctest-documentation/Classes/XCTestRun.html
Related
Let's say we have custom analytics library to track screen views and users actions. Considering following options.
// Option A
func buyButtonTap() {
doSomething()
doSomethingElse()
Analytics.track(event: .buy)
}
// Option B
func buyButtonTap() {
Analytics.track(event: .buy)
doSomething()
doSomethingElse()
}
Which option would you prefer? Does it matter at all? We have to consider following:
1) Our app and analytics library both use real-time networking and data streaming.
2) "Do something" procedures can be complex and expensive.
Personally, I think that tracking should happen in the end of procedure. And the reason is, that adding tracking in the beginning can add a bit of lag to the app when resources are scarce.
Tracking is not about the main thread, it's a fire-forget task. I think you should call the tracking function in the background thread and don't worry about main thread lag.
func buyButtonTap() {
DispatchQueue.global(qos: .background).async {
Analytics.track(event: .buy)
}
doSomething()
doSomethingElse()
}
So it depends for example.
if butbuttonTap() is a operation which process the tap operation then you should use option A
// Option A
func buyButtonTap() {
doSomething()
doSomethingElse()
Analytics.track(event: .buy)
}
but if butbuttonTap() includes placing order buying items then you should include before the operation as it can crash without finishing doSomething() and doSomethingElse(). then use
// Option B
func buyButtonTap() {
Analytics.track(event: .buy)
doSomething()
doSomethingElse()
}
Ideal case is to fragment your method into small parts and make your structure like option A i.e. calling analytics at the end.
as analytics generally used as didBuy or didTapBuy.
How does coroutines default scope work if i do not specify anything. lets take a look at this example:
class MyAppCompatActivity:AppCompatActivity{
fun getContact() {
GlobalScope.launch {
val contact = contacts.getContact() // suspended function
withContext(Dispatchers.Default) {
phoneContact.value = contact }
}
}
}
which simply updates the UI when a contact is retrieved. this is added to the global scope of so the coroutine life span can be that of the entire application.
but lets do the same thing again without a globalScope:
class MyAppCompatActivity:AppCompatActivity{
fun getContact() {
launch {
val contact = contacts.getContact() // suspended function
withContext(Dispatchers.Default) {
phoneContact.value = contact }
}
}
}
what is the lifespan of getContact now that i have removed the globalScope ? is it tied to the MyAppCompatActivity scope ?
Your code will fail to compile because launch must be called on a CoroutineScope object. This object specifies the lifespan of the coroutine. Since your activity does not implement a scope it will fail to compile or call a completely unrelated launch function.
I don't think this is a good idea anymore, as it looks like they're just functions for testing (doesn't launch coroutines). Maybe this was an API available previously, but now you should be using lifecycleScope to scope a coroutine to a fragment or activity, and viewModelScope to scope them to a View Model's life cycle. These are properties available in those classes by already.
Here's what I see when I try to use launch:
My test suite contains some test cases. I have some private functions where I will check elements existence. Consider I have three test cases:
func test_1() {
...
checkListViewElements()
...
}
func test_2() {
...
}
func test_3() {
...
checkListViewElements()
...
}
private func checkListViewElements() {
//Checking existence
}
Since I consider each test case as independent, the private function checkListViewElements() may get repeat within the test cases.
Problem:
When I run the whole test suite, all the three test cases(test_1, test_2 and test_3) will be executed.
The private method checkListViewElements() will be called twice. This will result with the increased amount of test suite completion time.
What I wanted:
I have so many functions like checkListViewElements() within my code. I want them to run only once when I run the whole test suite. (Remember, for each test case, the application terminates and open freshly)
What I tried:
var tagForListViewElementsCheck = "firstTime" //Global variable
private func checkListViewElements() {
if tagForListViewElementsCheck == "firstTime" {
//Checking existence
tagForListViewElementsCheck = "notFirstTime"
}
else {
//Skip
}
}
If I use local variables as tag, it works fine. But here, I have to create each tag for each private method. I really hated that.
I tried with dispatch_once and it seems not supported in Swift 4
Then I tried with static structs by referring this. It also does not seems working.
If there is any other nice approach to do it? Thanks in advance!
You may use function func setUp(). Its call only once per suite. More info at What is the purpose of XCTestCase's setUp method?.
I would like to take a screenshot on every fail test in a Spec or Suite using ScalaTest.
The Scala Test website shows how to take screenshots surrounding every code that might fail with this:
withScreenshot {
drive.findElement(By.id("login")).getAttribute("value") should be ("Login")
}
There is this post that tries to explain, but I could not understand what exactly should be done.
I also found the class ScreenshotOnFailure.scala, but could not use it, once it's private and has a package restriction.
Can anyone tell me if there's a way to intercept any failure and then take a screenshot?
Just to have a final answer I'm writing the way I could solve the problem based on the approach from this post mentioned in the question.
In short, the solution ended up like this (pseudo-code).
trait Screenshots extends FunSpec {
...
override def withFixture(test: NoArgTest): Outcome = {
val outcome = test()
// If the test fails, it will hold an exception.
// You can get the message with outcome.asInstanceOf[Failure].exception
if (outcome.isExceptional) {
// Implement Selenium code to save the image using a random name
// Check: https://stackoverflow.com/questions/3422262/take-a-screenshot-with-selenium-webdriver
}
outcome
}
}
class MySpec extends Screenshots {
...
describe("Scenario A") {
describe("when this") {
it("the field must have value 'A'") {
// It will save a screenshot either if the selector is wrong or the assertion fails
driver.findElement(By.id("elementA")).getAttribute("value") should be ("A")
}
}
}
}
From this point on, all Specs that extend the Screenshot trait will intercept errors and save a screenshot.
Just to complement, surrounding areas with withScreenshot(), as mentioned in the question, saves only failure on assertions, but it does not save a screenshot when the test fails due an element not found (e.g. wrong selector).
With the code above, all failures will save a screenshot.
this has already been answered but the solutions have not been working out for me.
Activiti asynchronous behaviour is fairly simple and only allows the user to enable a flag which tells activiti engine to insert such task in a execution queue (managing a pool of threads).
What i want is not to insert my java service task in a pool but to passivate its behaviour and only complete such task when an external signal is received and/or a callback is called.
My attempt:
class customAsyncTask extends TaskActivityBehavior {
override def execute(execution: ActivityExecution): Unit = {
val future = Future {
println(s"Executing customAsyncTask -> ${execution.getCurrentActivityName}, ${cur}")
}
future.onComplete {
case Success(result) => leave(execution)
case _ => // whatever
}
}
def signal(processInstanceId : String, transition : String) = {
val commandExecutor = main.processEngine.getProcessEngineConfiguration.asInstanceOf[ProcessEngineConfigurationImpl].getCommandExecutor
val command = new customSignal(processInstanceId, transition)
commandExecutor.execute(command)
}
}
On my previous code sample i have registered a scala future callback which when called will terminate the current activity and move to the next.
I also have a signal method which builds a custom signal that based on the processId and a name will call execution.take with the appropriate transition.
On both cases i am getting the following error (the bottom stack changes a little)
java.lang.NullPointerException
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.take(ExecutionEntity.java:453)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.take(ExecutionEntity.java:431)
at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performOutgoingBehavior(BpmnActivityBehavior.java:140)
at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performDefaultOutgoingBehavior(BpmnActivityBehavior.java:66)
at org.activiti.engine.impl.bpmn.behavior.FlowNodeActivityBehavior.leave(FlowNodeActivityBehavior.java:44)
at org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior.leave(AbstractBpmnActivityBehavior.java:47)
Unfortunately, it is highly likely that the engine is erasing the information concerning the execution when the execute method returns, even though no complete/leave/take has been called. Even though my callback has the execution object in context, when i query for information using its proccess ID all i receive is null.
So, what i am doing wrong here? How can i achieve the behaviour that i want?
I dont see anything specific, I would have said you need to extend a class that implements SignalableActivityBehavior, but I think TaskActivityBehavior actually does this.
While the stack indicates the NPE is coming from the leave(), I am confused why leave is calling "take" since take is a transition event and really should only happen on a task labeled as synchronous.
All I can offer is, Camunda have an example implementation that is similar to your scenario. You may be able to use this to help you:
https://github.com/camunda/camunda-bpm-examples/tree/master/servicetask/service-invocation-asynchronous
It seems that activiti uses thread local variables which means that when calling methods from the scala threads (scala Executor Context) would be pointless since they do not share the context.
To solve all i have to do from my callback is make a signal call much like if i were calling from a remote system. The only difference is that i do not need to save my process instance identifier.
The code looks as such:
class AsynchronousServiceTask extends AbstractBpmnActivityBehavior {
val exec_id : String = "executionId"
override def execute(execution : ActivityExecution) = {
val future = Future { println("Something") }
future onComplete {
case _ => myobject.callSignalForMe(execution.getId)
}
}
override def signal(execution : ActivityExecution, signalName : String, signalData : AnyRef) = {
println("Signal called, leaving current activity..")
leave(execution)
}
}
Basically, myobject holds the runTimeEngine and will inject the signal in a ThreadLocal context. All clean and working as intended.