Contributions
Re: Discarded Requests
To elaborate a little bit more, when you generate requests faster than your server responds, your 'running' count starts going up til it reaches its limit (setting in loadui). Once that happens all subsequently generated request starts getting lined up in 'queued'. That means LoadUI is waiting for running count to go below the limit to send these requests to your server. If this 'queued' count also reaches its limit (another loadui setting), then any subsequently generated request starts getting discarded. Means they will never get sent to your server. Failed means request was sent, but an invalid/unexpected response was received. For SoapUI Runner, it may be an assertion fail, or a test step fail. For Web runner it may be an invalid HTTP response, etc. So to compare 'discarded' and 'failed', former means request never sent to server as it's being generated too fast to go over limit set in loadui setting, while the later means the request was indeed sent to the server (assuming no prior test step execution failed), but an invalid/unexpected response was received.13 years agoPlace ReadyAPI QuestionsReadyAPI Questions1.3KViews0likes0CommentsRe: Load ui does not install
I faced installation issue with load ui few times. What I did was uninstall it and java fx too. Also I went to registry and manually deleted all loadui entries. Not sure if it was one of the root cause or not, but I noticed it didnt run with Java 7. So I uninstalled 7 and got Java 6. Try it out, see if that helps you with your issue.13 years agoPlace ReadyAPI QuestionsReadyAPI Questions1.7KViews0likes0Comments- 13 years agoPlace ReadyAPI QuestionsReadyAPI Questions1.3KViews0likes0Comments
- 13 years agoPlace ReadyAPI QuestionsReadyAPI Questions1.3KViews0likes0Comments
Re: Share your components here
Component name: Rate Multiplier Developer: Abhishek Dasgupta Description: Multiplies the rate of attached Generators (rate based) for easy load setting increase/decrease while keeping the load distribution ratio intact. Source code: /** * Multiplies the rate of attached Generators (rate based) for easy load increase/decrease * while keeping the load distribution ratio intact. * * @name Rate Multiplier * @nonBlocking false */ import com.eviware.loadui.util.layout.DelayedFormattedString import java.lang.Math // inputs and outputs createOutput('multiplierOutput', 'Multiplier', 'Multiply current rate with') // properties createProperty('multiplicationFactor', Long, 1) { newRate, oldRate -> displayFactor.setArgs(multiplicationFactor.value) if (oldRate == null) { oldRate = storedRate } adjustRate(oldRate, newRate) } displayFactor = new DelayedFormattedString('x %d', 200, multiplicationFactor.value) storedRate = multiplicationFactor.value calculatedNewRate = 1; calculatedNewUnit = 'Sec' onRelease = { displayFactor.release() } def adjustRate(oldRate, newRate) { def connectedComponent for (c in multiplierOutput.connections) { connectedComponent = c.inputTerminal.terminalHolder if (connectedComponent.category == 'generators') { //Supports only the generators with 'rate' property //Assumption is it will also have a 'unit' property with Sec, Min, Hour as possible values if (connectedComponent.getProperty("rate") != null) { def generatorRate = connectedComponent.getProperty("rate").value def generatorUnit = connectedComponent.getProperty("unit").getStringValue() calculateRateAndUnit(oldRate, newRate, generatorRate, generatorUnit) connectedComponent.getProperty("rate").value = calculatedNewRate connectedComponent.getProperty("unit").setValue(calculatedNewUnit) } } } } def calculateRateAndUnit(oldRate, newRate, generatorRate, generatorUnit) { //Convert rate to hour for easier calculation def multiplyBy = 1; if (generatorUnit == 'Sec') { multiplyBy = (60 * 60) } else if (generatorUnit == 'Min') { multiplyBy = 60 } calculatedNewUnit = 'Hour' calculatedNewRate = (generatorRate * multiplyBy) //Round rate if (newRate > oldRate) { calculatedNewRate = Math.ceil((calculatedNewRate * newRate) / oldRate) } else { calculatedNewRate = Math.floor((calculatedNewRate * newRate) / oldRate) } if (calculatedNewRate == 0) { calculatedNewRate = 1 } //Normalize if ((calculatedNewRate % 60) == 0) { calculatedNewUnit = 'Min' calculatedNewRate = (calculatedNewRate / 60) if ((calculatedNewRate % 60) == 0) { calculatedNewUnit = 'Sec' calculatedNewRate = (calculatedNewRate / 60) } } } // main layout layout { property(property:multiplicationFactor, label:'Multiplier', min:1) separator(vertical:true) box(widget:'display') { node(label:'Multiplication Factor', fString:displayFactor, constraints:'wmin 75') } } // compact layout compactLayout { box(widget:'display') { node(label:'Multiplication Factor', fString:displayFactor) } } // basic settings tab settings(label:'Basic') { property( property:multiplicationFactor, label:'Multiplication Factor') } Note: This currently works only with rate based generators, i.e. Fixed, Random and Variance. If multiplier is changed very rapidly and randomly, error might get thrown from the random generators due to a previously reported bug (viewtopic.php?f=12&t=12859) As rate is a whole number, changing multiplier value back-n-forth may not bring the initial rate setting back due to rounding up/down operation done during rate value calculation. Any suggestion to improve the component is most welcome.13 years agoPlace ReadyAPI QuestionsReadyAPI Questions4.3KViews0likes0CommentsRandom Generator
If rate along with unit (optionally) is changed too frequently, e.g. through another custom component, following error is thrown (seen on java web start console) - java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextEntry(Unknown Source) at java.util.HashMap$KeyIterator.next(Unknown Source) at com.eviware.loadui.groovy.GroovyContextSupport.cancelTasks(GroovyContextSupport.java:256) at sun.reflect.GeneratedMethodAccessor71.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1055) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:885) at org.codehaus.groovy.runtime.InvokerHelper.invokePojoMethod(InvokerHelper.java:781) at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:772) at com.eviware.loadui.groovy.GroovyScriptSupport$ScriptMetaClass.doInvokeMethod(GroovyScriptSupport.java:221) at com.eviware.loadui.groovy.GroovyScriptSupport$ScriptMetaClass.invokeMethod(GroovyScriptSupport.java:202) at groovy.lang.GroovyObjectSupport.invokeMethod(GroovyObjectSupport.java:44) at groovy.lang.Script.invokeMethod(Script.java:78) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeOnDelegationObjects(ClosureMetaClass.java:407) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:346) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:885) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:137) at GroovycomeviwareRandom$_run_closure3.doCall(GroovycomeviwareRandom:82) at sun.reflect.GeneratedMethodAccessor70.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:885) at groovy.lang.Closure.call(Closure.java:405) at groovy.lang.Closure.call(Closure.java:418) at com.eviware.loadui.groovy.GroovyContextSupport$2.handleEvent(GroovyContextSupport.java:211) at com.eviware.loadui.util.events.EventSupport$PendingEvent.run(EventSupport.java:160) at com.eviware.loadui.util.events.EventSupport$1.run(EventSupport.java:43) at java.lang.Thread.run(Unknown Source) Also Base Rate value and displayed Current Rate gets out of sync.13 years agoPlace ReadyAPI QuestionsReadyAPI Questions3.3KViews0likes3CommentsComponent Documentation
Custom component documentation (http://www.loadui.org/Developers-Corner ... categories) specifies generator category as 'generator'. But in reality it is 'generators' (see the groovy code of any generator component). So if any component checks for 'generator' category as per documentation, it'll never find a match. Also the documentation (http://www.loadui.org/Developers-Corner ... properties) specifies that terminals can be created with 1 or 2 parameters. But in reality it can take up to 3 parameters - name, short description and long description. Please fix the documentation. A little unrelated to documentation, I tried to output message to a TableLog using send method, but could never see anything getting displayed. Any help/guidance on it will he appreciated.13 years agoPlace ReadyAPI QuestionsReadyAPI Questions2.2KViews0likes2CommentsRe: Viewing Failed Tests
LoadUI has 2 pools, running and queue. Cap for those pools can be set at project level, also it can be set at each runner level (capped by the project level). Running pool gets filled up as requests get generated by generator. When a response is received, that thread is taken off that pool. But if that pool is filled up (as requests are being generated faster than responses are received), then subsequently generated requests starts going into Queued pool. If running count goes below cap, then requests from Queued gets into running pool. But if Queued pool also gets filled up, then any request generated after that gets discarded. And that's the discarded count. So basically for your case, 1697 tests ran. Among that 103 failed. But your response times were big enough to make running and queued pools get filled up. So 3000 generated requests got discarded. To capture request for failed tests, I think, there are 2 ways - 1. Create test case properties. Create property transfer step(s) to capture input and output in the test case. Configure corresponding runner to output testcase properties. Attach output of that runner to a table log. Downside of it is total time taken for that test case will get skewed a bit by few ms taken by property transfer step(s). So if your test case response time is in ms, then it's a big skew, but if it's in few seconds, then ignorable. 2. Use Condition component to detect a failure and output the request data to a table log. I havent yet tried this one. But I think it'll serve the purpose well.13 years agoPlace ReadyAPI QuestionsReadyAPI Questions812Views0likes0CommentsRe: Report Doesnt Work
I understand the performance issue. Yeah, it makes sense that the tool's internal performance is of utmost importance to capture proper performance data for the application under load. How about having an option to enable/disable debug? In debug mode it'll log all request/response data. Yeah I understand the hard-disc, network, etc. constraints. But this mode will be very helpful for setting up the load tests. To make sure load is cycling through proper data set, it is getting expected response from app, etc. Load tests are performed by technical people. So I'm sure they'll know how to use a debug mode (provided it's mentioned in documentation to know where to find this option ). Also I believe in load test we expect almost all of our requests to pass. So if in debug disabled mode the tool just logs request/response for the failed ones, will it impact tool's performance much? Regarding 'four depths' - 1. It generates reports on total response time of a test case. Wish it could be configurable to generate for request's response time. 2. This one I found very useful. But it has its own set of bugs (I've reported few of them in my other posts). 3. Havnt tried it yet, as it's not part of 1.5.0. But correct me if I misunderstood this component - This will only tell if a response time is beyond an acceptable level or such other constraints, but not for what request input it was not met. For example, if my constraint says 2 sec response time, it'll say that a response received, lets say, after 3 seconds. And it will say exactly at, for example, 1:30 PM. But it wont say what was my request data. So I cannot take the data and run it in isolation to figure out if the poor response was due to data or something else. 4. This one looks promising. Havent tried it yet. But looks like this might serve our purpose, if we can configure it to detect failures and then capture the request. Regarding graphs - Yes, I'm aware of the detail levels. But the issue is I can't print or save (as pdf) the entire graphs, when it's anything other than overall and spans more than the screen width. If I do, it only shows the portion that is visible on screen. For example, if I change zoom level to minutes, and print/save it, the printed/saved copy will have only half an hour worth graph. I'm guessing this might have something to do with paper width. But I suppose the solution would be to generate the graphs in multiple segments. I know I have made several threads about LoadUI. So dont get me wrong. I like this tool, a lot. But I think it has room for improvement and currently few bugs are making things a little difficult. So to get those fixed and to see this tool become robust I put my suggestions/concerns.13 years agoPlace ReadyAPI QuestionsReadyAPI Questions1.4KViews0likes0CommentsRe: [Resolved] Request count is not correct
If you read the article at the link above your post, it explains the counts clearly. I was confused too at the beginning to be honest. To give an explanation to your scenario quickly, discard happens when 'running' and then 'queued' for that runner fills up. For example, lets say your runner has setting of 10 concurrent thread to run, and 100 as queue. Now generator starts generating load, so they go in 'running', if response doesnt come soon enough, then running count will start increasing. When it reaches 10, any subsequent generated request will go to 'queued'. If 'running' goes below 10 (your setting), then requests from 'queued' will go in 'running' state. Now if 'queued' also gets filled up, then any subsequent generated request will get discarded. So basically, Requests = Running + Queued + Completed + Discarded Failed is just an informational number. Doesn't get counted in that equation (though IMO it should). But I do agree, from your example it seems the counts are indeed wrong. As per the flow chart (shown in the linked page), discarded shouldn't count towards completed. But it seems it did. Also I think the flowchart should be updated a bit. Instead of 'Send Request', it should say 'Run Test Case' and instead of 'Response Received or Timed Out', it should say 'Test Case Run Finished or Timed Out'. The reason is, if there's a failure in test case step execution, even then the failure count gets increased.13 years agoPlace ReadyAPI QuestionsReadyAPI Questions1.6KViews0likes0Comments