jmeter: access testplan name in sampler - groovy

We are developing some test cases using JSR-223 samplers ( groovy lanquage). We have some configuration information that is loaded at run time that keys off the TestPlan name. I don't see a means for accessing the testplan or name from the sampler, or sampler result. Is there a means to do so?

Here it is:
import org.apache.jmeter.services.FileServer;
String script = FileServer.getFileServer().getScriptName();
You can do the same using __TestPlanName() function passing via "Parameters" section
References:
FileServer class JavaDoc
How to Use JMeter Functions
UPDATE
Theoretically it is possible to access JMeter Test Plan tree, but remember, every time you bypass Java limitation using Reflection somewhere somehow a kitten dies.
Example code:
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.testelement.TestPlan;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.collections.SearchByClass;
import java.lang.reflect.Field;
import java.util.Collection;
StandardJMeterEngine engine = ctx.getEngine();
Field test = engine.getClass().getDeclaredField("test");
test.setAccessible(true);
HashTree testPlanTree = (HashTree) test.get(engine);
SearchByClass<TestPlan> testPlans = new SearchByClass<>(TestPlan.class);
testPlanTree.traverse(testPlans);
Collection<TestPlan> testPlansRes = testPlans.getSearchResults();
for (TestPlan testPlan : testPlansRes) {
log.info(testPlan.getProperty("TestElement.name").toString());
}
Demo:
You can check out How to Use BeanShell: JMeter's Favorite Built-in Component for more information on using JMeter and Java API.

Related

Jmeter - declare array variable in one JSR223 Sampler in order to access it in another JSR223 Sampler

So I have 2 JSR223 samplers in Jmeter Thread Group.
In the first one, I declare an empty array list
import java.util.List;
import java.util.ArrayList;
myList = new ArrayList();
In the second JSR223 Sampler, that is inside ForEach Controller, I am trying to access myList variable in order to add some value
import java.util.List;
import java.util.ArrayList;
myList.add(vars.get('trace_id'));
I keep getting the message
Response message: javax.script.ScriptException: groovy.lang.MissingPropertyException: No such property: myList for class: Script468
I was reading this (not official Jmeter docs though) and it says that By default, creating any new variables are local to a thread. It can not be accessed by other threads in the same thread group / other thread groups in the Test plan. so I was thinking I do everything right.
Is it possible to access the variable declared in one groovy sampler (JSR223) in another JSR223 sampler or I am trying to achieve not feasible scenario here?
to do that, in first JSR223 Sampler add this:
vars.putObject("myList", myList);
In second one:
def myList = vars.getObject("myList");
See javadocs:
https://jmeter.apache.org/api/org/apache/jmeter/threads/JMeterVariables.html

Using findElement in groovy pages

Apologies if this question seems trivial,.. but I am very very new to groovy/selenium as part of a maven system I’ve been thrown at and am in need to understand what I am missing in trying to get this method to work.
The error I am getting is below:
groovy.lang.MissingMethodException: No signature of method: GebConfig.findElement() is applicable for argument types: (org.openqa.selenium.By$ByName)
I’m in need to locate elements on a web page and would like to use the findElement method, however my code is in groovy as part of step definitions.
I have ended up with the following after lots of attempts but am getting nowhere:
package step_definitions
import features.support.Requests
import geb.*
import org.apache.commons.io.*
import org.openqa.selenium.By
import org.openqa.selenium.WebDriver
import org.openqa.selenium.WebElement
import org.openqa.selenium.*
import org.openqa.selenium.remote.*
import cucumber.api.groovy.EN.*
When(~/^find the element named "(.*?)"$/) { String btnName ->
WebElement myElement = driver.findElement(By.name(btnName));
}
I know I can use things like the below for a button and similar for other things like radio buttons and input fields:
browser.$(‘input’, name: ‘btnK’)
$(‘input’, name: ‘btnK’)
But I’d prefer to know how to use the findElement approach.
Any help would be appreciated.
Thanks,
Jim…..
I can see that you are using Geb with Cucumber JVM. If you've setup your environment using geb.binding.BindingUpdater as described in http://gebish.org/manual/current/#writing-your-own-steps then the methods and properties available in your steps are as listed in http://gebish.org/manual/current/#browser-methods-and-properties. You will notice that there is no driver property in that list - if you wish to access the driver instance then you will have to obtain it from browser:
When(~/^find the element named "(.*?)"$/) { String myName ->
WebElement myElement = browser.driver.findElement(By.name(btnName));
}

Python Twisted continuous reconnect attempts

When trying to connect a factory I want it to periodically try to reconnect if it fails to do so. I tried it with a code looking like that:
def reconnect():
print("this sucks")
reactor.connectTCP("localhost", 6667, factory2)
factory2 = pb.PBClientFactory()
factory2.clientConnectionFailed(reconnect(), "reasons")
reactor.connectTCP("localhost", 6667, factory2)
If I run this code it prints "this sucks" just once, although calling the connectTCP method with factory2 as parameter again. How should I go about implementing the desired behavior?
clientConnectionFailed is a method that is called by Twisted on a factory when a connection attempt fails. The usage in your example is nonsensical.
See ReconnectingClientFactory for one solution:
from twisted.internet.protocol import ReconnectingClientFactory
from twisted.internet import reactor
from yourlib import YourProtocol
factory = ReconnectingClientFactory()
factory.protocol = YourProtocol
reactor.connectTCP(host, port, factory)
reactor.run()
However, this does not combine well with PB due to the use of a custom factory class to support PB. This is just one of many reasons to avoid using PB at all.
A more recently introduced solution is ClientService:
from twisted.application.internet import ClientService
from twisted.internet.endpoints import HostnameEndpoint
from yourlib import YourFactory
factory = YourFactory()
service = ClientService(
HostnameEndpoint(reactor, host, port),
YourFactory(),
)
service.startService()
reactor.run()
Note I've skipped over correct "service" usage here for brevity; see the Twisted
service documentation for details on correct usage.

How to define a global class in SoapUI as a groovy script?

I want to define a class in a groovy script that i could reuse trough other groovy script inside SoapUI.
I alredy tried to define my class inside a TestSuite property but it doesn't work. I would like to avoid defining the class in a JAR because we work in team and every one would have to import the JAR in their SoapUI in order to run my tests. I use SoapUI 3.6.1
Here's how my TestSuite is made :
TestSuite
TestCase
TestSteps
Init (Groovy Script)
GetResponse1 (Test Request)
Test1 (Groovy Script)
GetResponse2 (Test Request)
Test2 (Groovy Script)
To simplify me tests, i defined a class in 'Test1' and i would like to reuse this class in 'Test2'. So ideally i would define that class in 'Init' and it would be accessible to any other groovy script.
How can i achieve that?
Based on #Abhey Rathore's link, here is how to define a global class in SoapUI's groovy script:
Step 1: Declare the global class
Create a project called MyRepository
Under this project create a disabled TestSuite called lib
Under this test suite create a TestCase called MyClass
Under this test case create a groovy script called class
Your project tree should look like the image below:
Step 2: Write the global class code
Inside the groovy script called class, copy and and paste the code below:
class MyClass {
// The three following fields are MANDATORY
def log
def context
def testRunner
// The constructor below is MANDATORY
def MyClass(logIn, contextIn, testRunnerIn) {
this.log = logIn
this.context = contextIn
this.testRunner = testRunnerIn
}
def myMethod() {
this.log.info 'Hello World!'
}
}
// Other scripts elsewhere in SoapUI will access the reused class through their context
context.setProperty( "MyClass", new MyClass(log, context, testRunner) )
Step 3: Import the global class
From any project, you can import the global class by using the following snippet:
// Import the class
def currentProject = testRunner.testCase.testSuite.project
currentProject
.testSuites["lib"]
.testCases["MyClass"]
.testSteps["class"]
.run(testRunner, context)
// Now use it
context.MyClass.myMethod()
SoapUI 5.2.1
try this, I think will help you in reusable code.
http://forum.soapui.org/viewtopic.php?t=15744
I am pretty sure that you will have to create a JAR file and put it in \bin\ext.
SoapUI will automatically pick it up on restart (you should see it mentioned in the startup stuff).
You basically just create a Java or Groovy project, Export it (with Eclipse) and it will work. SoapUI will probably have your dependencies covered, but if not you can add those JARs too (safer than creating a runnable JAR since SoapUI might use different versions of what you use).
If you need help, post related questions.
In SoapUI 5.3.0 you can use properties that can be set and get on the context variable. That variable is available in script assertion snippet.
For example:
context.setProperty("prop", "value");
And from different test script you can get the value by:
context.getProperty("prop");
You can use the property from when you define property as a step of test suite or as a value for field in header. You can do it by ${=context.getProperty("prop");}
Write this into your Project's load script, then reload your project or just run it.
com.eviware.soapui.support.ClasspathHacker.addFile( project.context.expand('${projectDir}') )
After it has run, you can now put .groovy files into the same folder as your soapui project xml. Plus, there is no need to compile anything.
e.g. in MyClass.groovy:
class MyClass {String name}
You can import those classes as normal in all your other scripts:
import MyClass
assert new MyClass(name:"me") instanceof MyClass
The only caveat is that your load script (the one setting the classpath), cannot have those imports, because the script will fail to compile. If you want to import something during your project load script, just have your load script 'evaluate' another groovy script (in other words, run it), in which you can use the imports:
evaluate (new File (project.context.expand('${projectDir}') + 'myProjectLoadScript.groovy'))
//in myProjectLoadScript.groovy:
import MyClass
/* Do things using MyClass... */
This seems the easiest way to me, so I'm not sure why I couldn't find this answer elsewhere online.

What is the best way to import constants into a groovy script?

I have been setting up a scripting envrionment using Groovy. I have a groovy script called FrameworkiDatabase.groovy which contains a class of the same name. This works fine. I also have another file called connections.groovy which contains maps like the following:
SUPPORT2=[
host:"host.name",
port:"1521",
db:"support2",
username:"username",
password:"password",
dbType:"oracle"
]
This holds a collection of database bookmarks, a bit like an oracle tnsnames file, so I don't need to remember all the parameters when connecting to databases.
When using groovysh, I can import this using the load command, and it is available in current scope. How can I load it as part of a script the same way? It has no class definition around it - does it need one? I have tried doing that, and adding a static import, but that didn't work...
I tried something like this, but no luck:
testFrameworkiDatabase.groovy:
import static connections
def db = new FrameworkiDatabase(SUPPORT2)
db.listInvalidObjects()
db.getDBSchemaVersion()
db.getFWiVersion()
db.getSPVersion()
db.getFileloaderVersion()
db.getAdminToolVersion()
db.getReportsVersion()
So I want to load those connections as constants - is there any way I can do this easily?
Not sure if it's the best way, but one way would be to write this into Connections.groovy
class Connections {
static SUPPORT2 = [
host:"host.name",
port:"1521",
db:"support2",
username:"username",
password:"password",
dbType:"oracle"
]
}
Then, compile this with groovyc Connections.groovy to generate a class file
Then, in your test script or on the groovysh prompt, you can do:
import static Connections.*
println SUPPORT2
To get the output:
[host:host.name, port:1521, db:support2, username:username, password:password, dbType:oracle]
If compiling the Connections.groovy class isn't good enough, I think you're going to be looking at loading the source into a Binding object by using one of the Groovy embedding techniques

Resources