- An improved PluginLoader that loads plugins into their own ClassLoader - allowing plugins to have 3rd party dependencies that don't collide with other plugins or SoapUI itself
- An annotation-based extension mechanism for creating plugin classes (no more XML...)
- An integrated PluginManager that allows you to install/uninstall/upgrade plugins via the UI
- A plugin-repository hosted by SmartBear to which you can submit your own plugins so anyone can download them via the PluginManager
- A maven archetype for easily creating new plugin projects using either java or groovy as the development language
Let's create a simple plugin to illustrate some of these steps.
Prerequisites
As you hopefully know - SoapUI is a desktop tool for all aspects of API Testing that you'll need to download and install from smartbear.com. Creating plugins is simplified by having a java/groovy development environment, for example Intellij or eclipse. You'll also need maven for the actual building of the plugins. I won't dive any more into this since I expect you to have all this sorted out already :-)
Creating a simple search plugin
The maven archetype will generate the basic plugin project for you; open a command-prompt in a folder where you want to create the plugin project and type the following:
mvn archetype:generate -DarchetypeGroupId=com.smartbear.maven.archetypes -DarchetypeArtifactId=soapui-plugin-archetype -Dmaven.repo.remote=http://www.eviware.com/repository/maven2
This will download and install the maven archetype and start generation of the plugin project. You will be prompted for a number of properties - set these as follows:
- groupId: "com.mycompany"
- artifactId : "my-soapui-plugin"
- version : "1.0.0"
- package : <empty>
- language : "java"
- type : "Action"
maven will do some work and generate the default project for you - you should see something in the line of the following in your command-prompt:
Now go into the created "my-soapui-plugin" directory and run "mvn install" from the command-line - this will build the plugin and package it for installation - you will get something like the following:
Let's install this plugin in SoapUI 5.1 - start SoapUI and open the PluginManager from the main toolbar:
Select the "Load plugin from file..." button at the bottom of the PluginManager dialog and navigate to the generated plugin in the target folder of the plugin project:
Press "Open" and the plugin should get installed:
Close the Plugin Manager and right-click on any open project in your SoapUI workspace (this is where the default plugin action is installed) - you'll see the plugin action at the bottom of the menu:
Presto - that was easy! Your first SoapUI Plugin is installed and running - and you didn't write one line of code!
Customizing the plugin to do a search in our project
Although it works - the plugin currently doesn't do much (it just shows a hello message). Let's improve the plugin to actually do something useful - search and open a list of matching items in the selected project.
Open the project in your java development environment (i'll leave the details of that to you...) and navigate to the PluginAction.java file that was generated via the maven archetype:
You can see the default implementation of the perform method - it just shows a "Hello from..." message in a popup window.
Now comes the hard part - knowing your way around the SoapUI object model and APIs - have a look at The SoapUI Object Model to get an introduction and pointers to relevant javadocs.
What we'll do is change the perform method to first prompt for a search string, then do a recursive search through all items in the select project to find those with a matching name (using the specified search string as a regular-expression) - and finally display the results in a ModelItemListDesktopPanel:
As you can see, I've also brushed up some of the metadata in the constructor - and the generated PluginConfig.java file has been updated accordingly:
together with updated metadata in the pom;
<name>SoapUI Search Plugin</name>
<artifactId>soapui-search-plugin</artifactId>
<groupId>com.smartbear.soapui.plugins</groupId>
Now when we build and install the plugin (uninstall the previous version first in the Plugin Manager) - we get the following item in the popup menu:
which prompts as follows when selected:
and uses the specified regular-expression to find items in the selected project and display them:
Double-clicking an item in this window opens the corresponding desktop panel for editing. Marvellous!
Next Steps
That's all there was to it - the plugin is ready to by submitted to the plugin repository and spread to thousands of SoapUI users out there.
The above plugin is available on GitHub - feel free to fork and improve it, ask questions or just use it.
And as always - I'm looking forward to hearing from you.
/Ole
Thanks for the excellent demonstration, Ole..!!
ReplyDeleteI am a frequent visitor of your blog. I would like to receive a favor from you, demanding a post on initial setup on SoapUI Plugin development environment using Eclipse and Maven. This seems to be erroneous when I try to start with plugin development. Could you please help in this regard.
Thanks,
Samy
Hi Samy,
ReplyDeletethanks for this - I'll try to write something up in this regard - please also consider signing up to the SoapUI plugin-development webinar (http://olensmar.blogspot.se/2014/07/getting-started-with-new-soapui-plugin.html) to learn more!
kind regards,
/Ole
Ole, Thanks for the consideration...!!! I have already registered for the suggested webinar. Awaiting to see you on that!
DeleteDoesn't work actually. Can't create project from archetype. Probably we have to use -DarchetypeCatalog=http://www.eviware.com/repository/maven2 instead of -Dmaven.repo.remote=http://www.eviware.com/repository/maven2 ?
ReplyDeleteAnd doesn't work for "TestStep" type:
ReplyDelete[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.345 s
[INFO] Finished at: 2014-10-02T11:14:09+02:00
[INFO] Final Memory: 12M/219M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.
1:compile (default-compile) on project averagetime-soapui-plugin: Compilation fa
ilure: Compilation failure:
[ERROR] C:\!WORK\SOA\SOAPUI\AverageReponseTime\averagetime-soapui-plugin\src\mai
n\java\com\andhr\soapui\PluginTestStep.java:[11,-1] 1. ERROR in C:\!WORK\SOA\SOA
PUI\AverageReponseTime\averagetime-soapui-plugin\src\main\java\com\andhr\soapui\
PluginTestStep.java (at line 11)
[ERROR] import com.eviware.soapui.plugins.auto.PluginTestStep;
[ERROR] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[ERROR] The import com.eviware.soapui.plugins.auto.PluginTestStep conflicts with
a type defined in the same file
[ERROR] ----------
[ERROR]
[ERROR] Found 2 errors and 0 warnings.
Any ideas?
Thanks for this - I'm really sorry for your troubles. You are correct, please use
ReplyDelete-DarchetypeCatalog=http://www.eviware.com/repository/maven2
instead of -Dmaven.repo.remote
I've uploaded an update to the plugin that should fix your issue with the TestStep type... please let me know if you're still having troubles. Thanks!
/Ole
Hi. New error :) :
DeleteConfirm properties configuration:
groupId: com.soapui.andhr
artifactId: average-test-step
version: 1.0.0
package: com.soapui.andhr
language: Java
type: TestStep
Y: : y
[INFO] -------------------------------------------------------------------------
---
[INFO] Using following parameters for creating project from Archetype: soapui-pl
ugin-archetype:1.0
[INFO] -------------------------------------------------------------------------
---
[INFO] Parameter: groupId, Value: com.soapui.andhr
[INFO] Parameter: artifactId, Value: average-test-step
[INFO] Parameter: version, Value: 1.0.0
[INFO] Parameter: package, Value: com.soapui.andhr
[INFO] Parameter: packageInPathFormat, Value: com/soapui/andhr
[INFO] Parameter: package, Value: com.soapui.andhr
[INFO] Parameter: version, Value: 1.0.0
[INFO] Parameter: groupId, Value: com.soapui.andhr
[INFO] Parameter: type, Value: TestStep
[INFO] Parameter: language, Value: Java
[INFO] Parameter: artifactId, Value: average-test-step
[ERROR] ResourceManager : unable to find resource 'Java/TestStep.inc' in any res
ource loader.
[ERROR] #parse(): cannot find template 'Java/TestStep.inc', called from template
archetype-resources/src/main/__language__/Plugin__type__.__language__ at (5, 1)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 59.361 s
[INFO] Finished at: 2014-10-07T13:49:28+02:00
[INFO] Final Memory: 15M/150M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:2
.2:generate (default-cli) on project standalone-pom: org.apache.maven.archetype.
exception.ArchetypeGenerationFailure: Error merging velocity templates: Unable t
o find resource 'Java/TestStep.inc' -> [Help 1]
hehe - please specify Java with all-small-caps; i.e. just "java" - does that help?
Delete/Ole
The new one :)
Delete[INFO] Using following parameters for creating project from Archetype: soapui-plugin-archetype:1.0
[INFO] -------------------------------------------------------------------------
---
[INFO] Parameter: groupId, Value: com.soapui.andhr
[INFO] Parameter: artifactId, Value: average-test-step
[INFO] Parameter: version, Value: 1.0.0
[INFO] Parameter: package, Value: com.soapui.andhr
[INFO] Parameter: packageInPathFormat, Value: com/soapui/andhr
[INFO] Parameter: package, Value: com.soapui.andhr
[INFO] Parameter: version, Value: 1.0.0
[INFO] Parameter: groupId, Value: com.soapui.andhr
[INFO] Parameter: type, Value: TestStep
[INFO] Parameter: language, Value: java
[INFO] Parameter: artifactId, Value: average-test-step
[WARNING] Can not override property: com.smartbear.soapui:soapui:jar
[WARNING] Can not override property: com.smartbear.soapui:soapui-pro:jar
[INFO] Try to merge plugin configuration of plugins with id: org.apache.maven.plugins:maven-compiler-plugin
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 30.714 s
[INFO] Finished at: 2014-10-07T15:19:08+02:00
[INFO] Final Memory: 15M/150M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:2.2:generate (default-cli) on project standalone-pom: Don't override file c:\!WORK\SOA\SOAPUI\AverageReponseTime\average-test-step\src\main\java\com\soapui\andhr\ActionGroups.java -> [Help 1]
wow - that looks really strange; did it really prompt you for all those parameters multiple times!? did you clean out your current directory before running? perhaps you could clean out the archetype from your local repo as well!?
Delete/Ole
Yes! It works now, i forgot to clean up my directory... But now, when i open project in eclipse it shows 2 errors in PluginTestStep.java
DeleteThe import com.eviware.soapui.plugins.auto.PluginTestStep conflicts with a type defined in the same file
Type mismatch: cannot convert from PluginTestStep to Annotation
Probably smth wrong with my environment, but i have several more projects and they work just fine...
Great! Did you clear out your locally cached archetype? The error you are getting should be fixed in the latest version... perhaps I should bump the version number...
Delete/Ole
Huh :) It would be great if you can point me how to do this.
DeleteForget about my previous comment. I've cleaned it up and now everything is fine. Thanks!
DeleteGreat - thanks for hanging in there - I'm sorry you had to discover all these issues :-)
DeleteDon't hesitate to ask for help regarding the actual TestStep...
/Ole
Yes! Your help would be just in time :) I already spent several days trying to get this (and also created topic on soapui forum):
DeleteI want to create test step that will get some info from all test step results e.g. response time for each of them and calculate average for the whole test suite. As i understand i have to access WsdlTestSuiteRunner and iterate thru all TestCaseRunners and TestStepResults. But how can i access WsdlTestSuiteRunner from public TestStepResult run (TestCaseRunner testRunner, TestCaseRunContext context)?
Hope you will share some light on this. Thanks in advance :)
Ok. I figured it out:
Deletepublic TestStepResult run (TestCaseRunner testRunner, TestCaseRunContext context)
{
WsdlTestSuite testSuiteNew = (WsdlTestSuite) testRunner.getTestRunnable().getParent();
for (TestCase testCase : testSuiteNew.getTestCaseList()) {
for (TestStep step : testCase.getTestStepList()) {
if (step instanceof RestTestRequestStep) {
RestTestRequestStep requestStep = (RestTestRequestStep) step;
if (requestStep.getTestRequest().getResponse() != null) {
averageTime = requestStep.getTestRequest().getResponse().getTimeTaken();
}
}
}
}
}.
In case if someone will need this
Hi Andrei,
DeleteGreat work - sorry for not helping, I'm just swamped with the Ready! API release... Regarding your code it looks fine - you could exchange RestTestRequestStep for HttpRequestTestStep and use HttpRequestTestStep.getHttpRequest().getResponse() instead - which would make this cover Http/Rest/Soap teststeps.
A separate concern could be that this will only capture the last response a certain teststep has handled - so if you are running loops or datasources in your testcase you would miss those responses -> you can access them by getting the testRunner for each executed TestCase instead (which exposes a getResults() collection containing TestStepResults for each time a TestStep was executed).
/Ole
Great, thanks. I will join "Assuring API Quality with the Extensibility of SOAPUI and Ready! API" workshop in Stockholm, October 20, so can imagine you have a lot of stuff to prepare :) good luck!
DeleteOle,
DeleteI have a doubt on the above comment:
"A separate concern could be that this will only capture the last response a certain teststep has handled - so if you are running loops or datasources in your testcase you would miss those responses -> you can access them by getting the testRunner for each executed TestCase instead (which exposes a getResults() collection containing TestStepResults for each time a TestStep was executed). "
Could you please help me in explaining more in detail. Currently, I face this kind of situation where I need to get responses of data driven tests done through DataSources.
/Samy
Hi Samy,
ReplyDeletecan you elaborate a little more on your setup? Perhaps you could use a DataSink TestStep to capture the responses for individual requests in a DataDriven test?
/Ole
Hi Ole,
ReplyDeleteI have download your search plugin in github example and build the jar with maven, and then put it in the .soapuios/plugins folder, but the plugin failed to added to the soapui with the ERROR:
2015-11-10 13:55:06,393 ERROR [SoapUI] An error occurred [The plugin 'C:\Users\lile10\.soapuios\plugins\soapui-search-plugin-1.0.0.jar' has unsigned class files.], see error log for details
2015-11-10 13:55:06,393 ERROR [errorlog] java.lang.SecurityException: The plugin 'C:\Users\lile10\.soapuios\plugins\soapui-search-plugin-1.0.0.jar' has unsigned class files.
java.lang.SecurityException: The plugin 'C:\Users\lile10\.soapuios\plugins\soapui-search-plugin-1.0.0.jar' has unsigned class files.
at com.eviware.soapui.plugins.ProductBodyguard$JarVerifier.verify(ProductBodyguard.java:107)
at com.eviware.soapui.plugins.ProductBodyguard.isKnown(ProductBodyguard.java:39)
at com.eviware.soapui.plugins.PluginManager.loadPlugins(PluginManager.java:93)
at com.eviware.soapui.DefaultSoapUICore.loadPlugins(DefaultSoapUICore.java:155)
at com.eviware.soapui.DefaultSoapUICore.init(DefaultSoapUICore.java:133)
at com.eviware.soapui.StandaloneSoapUICore.(StandaloneSoapUICore.java:38)
at com.eviware.soapui.SoapUI$SoapUIRunner.run(SoapUI.java:721)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
2015-11-10 13:55:06,393 WARN [SoapUI] Plugin 'soapui-search-plugin-1.0.0.jar' is not loaded because it hasn't been signed by SmartBear Software.
Hi Ole,
ReplyDeleteI am setting up env for plugin development. I am experimenting with sample codes in your blog, git, smartbear site etc.
I'm unable to figure out, how to listen for keyboard events. Could you please help me with that, would really appreciate it.
Thanks
Kumar
Hi Kumar,
DeleteThanks for posting! Are you trying to trigger a plugin-action from the keyboard? Or is the context something else?
thanks,
/Ole
Hi Ole,
ReplyDeleteI'm trying to maven generate as below:
mvn archetype:generate -DarchetypeGroupId=com.smartbear.maven.archetypes -DarchetypeArtifactId=soapui-plugin-archetype -Dmaven.repo.remote=http://www.eviware.com/repository/maven2
Choose archetype:
1: internal -> org.apache.maven.archetypes:maven-archetype-archetype (An archetype which contains a
sample archetype.)
2: internal -> org.apache.maven.archetypes:maven-archetype-j2ee-simple (An archetype which contains
a simplifed sample J2EE application.)
3: internal -> org.apache.maven.archetypes:maven-archetype-plugin (An archetype which contains a sam
ple Maven plugin.)
4: internal -> org.apache.maven.archetypes:maven-archetype-plugin-site (An archetype which contains
a sample Maven plugin site.
This archetype can be layered upon an existing Maven plugin project.)
5: internal -> org.apache.maven.archetypes:maven-archetype-portlet (An archetype which contains a sa
mple JSR-268 Portlet.)
6: internal -> org.apache.maven.archetypes:maven-archetype-profiles ()
7: internal -> org.apache.maven.archetypes:maven-archetype-quickstart (An archetype which contains a
sample Maven project.)
8: internal -> org.apache.maven.archetypes:maven-archetype-site (An archetype which contains a sampl
e Maven site which demonstrates
some of the supported document types like APT, XDoc, and FML and demonstrates how
to i18n your site. This archetype can be layered upon an existing Maven project.)
9: internal -> org.apache.maven.archetypes:maven-archetype-site-simple (An archetype which contains
a sample Maven site.)
10: internal -> org.apache.maven.archetypes:maven-archetype-webapp (An archetype which contains a sa
mple Maven Webapp project.)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 7:
What should I choose number??
When I choose number 7, "PluginAction.java" file is not generated.
Could you help me?
Hi!
ReplyDeleteplease post this as an issue on the https://github.com/SmartBear/ready-api-plugins repo - thank you!
/Ole