I'm familiar with unit testing Spring Batch job steps (and entire jobs), but am wondering if there is a way to unit test a "worker" step for a partition (without testing the whole partition step).
The thing I'm puzzling over is that typically a unit test for a step would call:
JobLauncherTestUtils.launchStep(stepName, jobParameters, jobExecutionContext)
But, this being a worker step within a partition, I need some way of also passing in a StepExecutionContext. Is there a way to do that?
Unless you don't trust Step implementations provided by Spring Batch, I would test the component (which needs to read values from the step execution context) used within the worker step and not the worker step itself. Let me give two examples:
Chunk-oriented worker step
In this case, I would unit test the component (reader, processor or writer) that needs to access a value from the step execution context and not the chunk-oriented step itself (which is provided by Spring Batch and should be trusted, unless you don't trust it).
Simple tasklet worker step
If the worker step is a simple tasklet, you can unit test the Tasklet itself and not the TaskletStep.
In both cases, the component (reader/processor/writer or tasklet) should be step scoped to get access to the step execution context and you can mock/stub the step execution context as needed. Please refer to the Testing Step-Scoped Components fro more details.
Related
Under heavy load we are experiencing a lot of OptimisticLockingException exceptions and job reties for some of our processes (which causes a lot of trouble).
When not under load, the orchestrator don't throw any OptimisticLockingException exception
Could you please suggest a way to locate which steps provoke these concurrent operations ?
170556:2021/01/21 21:35:04.022 DEBUG ENGINE-16002 Exception while closing command context: ENGINE-03005 Execution of 'UPDATE ExecutionEntity[223d44fe-5c28-11eb-aa7e-eeeccf665d52]' failed. Entity was updated by another transaction concurrently. {"org.camunda.bpm.engine.OptimisticLockingException: ENGINE-03005 Execution of 'UPDATE ExecutionEntity[223d44fe-5c28-11eb-aa7e-eeeccf665d52]' failed. Entity was updated by another transaction concurrently.":null}
170986:2021/01/21 21:35:04.107 WARN ENGINE-14006 Exception while executing job 23e3a29c-5c28-11eb-80a2-eeeccf665d52: {"org.camunda.bpm.engine.OptimisticLockingException: ENGINE-03005 Execution of 'UPDATE ExecutionEntity[223d44fe-5c28-11eb-aa7e-eeeccf665d52]' failed. Entity was updated by another transaction concurrently.":null}
107264:2021/01/21 21:35:36.407 DEBUG ENGINE-16002 Exception while closing command context: ENGINE-03005 Execution of 'DELETE TimerEntity[f723f288-5c27-11eb-aa7e-eeeccf665d52]' failed. Entity was updated by another transaction concurrently. {"org.camunda.bpm.engine.OptimisticLockingException: ENGINE-03005 Execution of 'DELETE TimerEntity[f723f288-5c27-11eb-aa7e-eeeccf665d52]' failed. Entity was updated by another transaction concurrently.":null}
If you can suggest a way to avoir retry of async task that would be great, as asked in this question
https://forum.camunda.org/t/how-to-avoid-retry-of-async-service-tasks-when-an-optimisticlockingexception-occurs/21301
Env :
2 instances of spring boot Camunda orchestrator
<camunda-bpm.version>3.4.0</camunda-bpm.version>
<camunda-engine.version>7.12.0</camunda-engine.version>
Postgres 9.12 with read_commited
OptimisticLockingExceptions are a mechanism to protect you from lost updates, which could otherwise result form concurrent access to the same execution data. One transaction updated the parent execution first (V1>V2). The process engine then makes the second transaction redo its operations (on V1, meanwhile stale), but this time based on the latest version of the execution (V2). The second transaction then creates new version of the execution (V2>V3)
So the OLEs can occur in places where concurrency occurs. Are you using parallel or inclusive gateways? Are events trigger concurrent token flow?
Understand when concurrency occurs in the process model / engine and evaluate if the concurrent execution is really needed. In many cases people model e.g. two service call in parallel, which only take milliseconds each. Then there is no gain in total processing time (creating and merging concurrent job also costs time), but the concurrency can become a burden. So prefer sequential execution where possible.
Check the duration of your transactions. If you have longer transaction combining multiple service calls, it can be helpful to split them into multiple jobs (it depends on the use case. more jobs also mean more transactions).
The most important best practice when dealing with OLE is checking async before on merging parallel gateways. This will not fully prevent the OLE, but the built-in retry mechanism of the job executor will take care of them for you.
Last but not least OLEs occur increasingly when the system is high load and the DB is not performing well. Tune the overall system performance to reduce DB load and OLEs.
We use camunda-bpm-assert and camunda-bpm-assert-scenario libs for Camunda processes unit testing (testing of .bpmn).
But i couldn't find any approach for signal testing - how can we verify, that signal with the right name and variables was thrown during test execution?
Appreciate any ideas.
It's a workaround, but if this is important to test, you could deploy another process in your test scenario that receives a signal and has a follow up task (or execution listener) that records the call and the variables, thus allowing you to assert on these.
I have created a framework in which I have used Set Browser Implicit Wait 30
I have 50 suite that contains total of 700 test cases. A few of the test cases (200 TC's) has steps to find if Element present and element not present. My Objective is that I do not want to wait until 30 seconds to check if Element Present or Element not Present. I tried using Wait Until Element Is Visible ${locator} timeout=10, expecting to wait only 10 seconds for the Element , but it wait for 30 seconds.
Question : Can somebody help with the right approach to deal with such scenarios in my framework? If I agree to wait until 30 seconds, the time taken to complete such test case will be more. I am trying to save 20*200 secs currently Please advise
The simplest solution is to change the implicit wait right before checking that an element does not exist, and then changing it back afterwards. You can do this with the keyword set selenium implicit wait.
For example, your keyword might look something like this:
*** Keywords ***
verify element is not on page
[Arguments] ${locator}
${old_wait}= Set selenium implicit wait 10
run keyword and continue on failure
... page should not contain element ${locator}
set selenium implicit wait ${old_wait}
You can simply add timeout="${Time}" next to the keyword you want to execute (Exp., Wait Until Page Contains Element ${locator} timeout=50)
The problem you're running into deals with issue of "Implicit wait vs Explicit Wait". Searching the internet will provide you with a lot of good explanations on why mixing is not recommended, but I think Jim Evans (Creator of IE Webdriver) explained it nicely in this stackoverflow answer.
Improving the performance of your test run is typically done by utilizing one or both of these:
Shorten the duration of each individual test
Run test in parallel.
Shortening the duration of a test typically means being in complete control of the application under test resulting in the script knowing when the application has successfully loaded the moment it happens. This means having a a low or none Implicit wait and working exclusively with Fluent waits (waiting for a condition to occur). This will result in your tests running at the speed your application allows.
This may mean investing time understanding the application you test on a technical level. By using a custom locator you can still use all the regular SeleniumLibrary keywords and have a centralized waiting function.
Running tests in parallel starts with having tests that run standalone and have no dependencies on other tests. In Robot Framework this means having Test Suite Files that can run independently of each other. Most of us use Pabot to run our suites in parallel and merge the log file afterwards.
Running several browser application tests in parallel means running more than 1 browser at the same time. If you test in Chrome, this can be done on a single host - though it's not always recommended. When you run IE then you require multiple boxes/sessions. Then you start to require a Selenium Grid type solution to distribute the execution load across multiple machines.
Currently I'm coding a network lib based on Boost asio.
I want to automatically test my lib with a kind of loopback echo test.
The problem is, that the server is running continuously thus the test never ends.
My idea is to do some EQUAL tests with response data and to manually stop the unit test with success. If a timeout occurs otherwise, the test should stop with fail (I know, it's more an integration test as an unit test)...
Is there a Boost Unit Test macro to manually stop the test with success?
Thanks!
You can just leave the test function, that will count as success. If you want to explicitly "set" the result, you can use BOOST_CHECK(true) for success and or BOOST_CHECK(false) for failure. There are variants of these macros with an additional message to be printed on failure (BOOST_CHECK_MESSAGE).
The test framework itself is single threaded and the individual tests run one after the other. Each test function has to end by either an explicit return statement or execution "falling off the end".
If you call a function that does not return by itself but needs some trigger to do so, you need to somehow schedule this trigger before calling the function. This might require starting a thread, waiting there for a certain time and then sending the trigger to cause the blocking function to return.
In summary:
How do I create "integration" tests that mimic expected delays from external systems?
In detail:
I have an application "Main" that communicates with multiple external systems (via web services) which I'll call "Partners".
I am disinterested in the inner workings of the Partners, but I need to fully test Main.
For Main I currently have:
Unit Tests for each individual testable block [so test every public method on every class at every "level" (n-tier) and stub every dependency]
Integration tests that test from the top-down (so test all public methods on the Presentation tier and stub only these partner web services)
What I would also like is to create some integration tests to ensure that the code in MAIN delivers the correct performance.
What is "correct performance"? Well, the Product Manager can say "all Views must return data within 2 seconds". I know that (on average) a call to a partner takes (say) 1.5 seconds so I could write my Integration test with a stop watch that passes if the Main code completed in 0.5 seconds (2 - 1.5). However, in a discussion with a colleague it was suggested that the Stub for the partner should include the 1.5 second expected delay, and so my test should be that the Main code plus stub for partner should complete within the 2 seconds as specified by PM.
QUs:
What is the suggested behaviour?
If as suggested, how is this achieved using Rino Mocks for stubbing?
Thanks everyone
Griff
"all Views must return data within 2 seconds" makes no sense. when limiting the response time, you should also consider the load. when there will be 1 request per 10 second then your views may return in 2 seconds. but when there will be 10k request per second then your response time will be "slightly" longer. better performance requirement would be "x% of responses will take not more then y seconds when load is below z requests per seconds" or something similar.
unit testing delays also makes no sense. you should run full scale performance tests. choose one of the existing tools, prepare a few client nodes (controlled with that tool), run recorded/scripted clients' requests against your tested server and check what are the response times, cpu and memory usage. then add one or mode nodes to your system and check how the system is scaling