For some reason, setup method doesn't recognize the closure that came before it, because when this code gets put into a test suite and ran, it throws
MissingMethodException about the closure I'm trying to call:
int initialNumberOfRows = 0
def findRowCount = {
initialNumberOfRows = 5
}
/**
* Some methods below are samples for using SetUp/TearDown in a test suite.
*/
/**
* Sets up test environment.
*/
#SetUp(skipped = false) // Please change skipped to be false to activate this method.
def setUp() {
// login and select the test company first
WebUI.callTestCase(findTestCase('Test Cases/TestCompanySelectGoesToDashboard'), [('shouldLogout') : false, ('shouldCloseBrowser') : false])
// go to the "Discounts" page
WebUI.click(findTestObject('PageMenuOptions/a_Discounts'))
// determine the row count
WebUI.delay(5)
findRowCount()
}
I run that code and get greeted with the following exception message:
groovy.lang.MissingMethodException: No signature of method: DiscountsSuite.findRowCount() is applicable for argument types: () values: []
The closure, as of right now, is a stub, but will be used to get the number of rows, after which we will delete as cleanup for the test suite (I make the rows via the test suite, I gotta clean em up!)
Related
I'm testing a class that uses Spring Boot's webflux library, and I've encountered strange behavior with StepVerifier::expectError. Specifically, I can pass any type (even String!) to the method and the test passes. My method under test should respond with an error Mono for this particular test, and the mono should contain a custom exception. My understanding from this SO question is that I have the StepVerifier operating in the correct block. What is going wrong here?
Class under test:
#Service
#RequiredArgsConstructor
public class PaymentsBO {
private final ContractClient contractClient;
public Mono<Void> updatePaymentInfo(Request record) {
return contractClient
.getContract(UUID.fromString(record.getContractUuid()))
.onErrorResume(throwable -> Mono.error(() -> new CustomException(
"Contract Service responded with a non-200 due to "
+ throwable.getCause())))
.flatMap(
// happy-path logic
);
}
}
Unit test:
def "Returns an error if the Contract Service returns a non-200"() {
given:
def testSubject = new PaymentsBO(contractServiceMock)
def contractServiceMock = Mock(ContractClient)
when:
def result = testSubject.updatePaymentInfo(record)
and:
StepVerifier.create(result)
.expectError(String.class)
then:
1 * contractServiceMock.getContract(CONTRACT_UUID) >> Mono.error(new ContractServiceException())
}
In StepVerifier docs we can read that verification must be triggered by calling one ot the verify methods
Trigger the verification of the resulting StepVerifier on its Publisher using either verify() or verify(Duration). (note some of the terminal expectations above have a "verify" prefixed alternative that both declare the expectation and trigger the verification).
https://projectreactor.io/docs/test/release/api/reactor/test/StepVerifier.html
Your code doesn't use a verify method.
Please consider these two cases:
#Test
void without_verify() {
Mono.error(new IllegalArgumentException(""))
.as(StepVerifier::create)
.expectError(NullPointerException.class);
}
#Test
void with_verify() {
Mono.error(new IllegalArgumentException(""))
.as(StepVerifier::create)
.expectError(NullPointerException.class)
.verify();
}
without_verify is passing because no verification has been triggered.
with_verify is failing because verification has been triggered.
I am working on a test case in Katalon Studio that fills out a prompt to add n rows to a table, and wish to, as teardown step, try to delete those rows. I have written the test deletion logic to a test case that I call from inside a closure. I then call that closure as a first step in the teardown. However, When I run the test, it silently fails to actually teardown. I get an error message like this
Error occurred when try to run method 'tearDown' (Root cause: org.codehaus.groovy.runtime.InvokerInvocationException - org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingMethodException: No signature of method: Script1529594455360.deleteRowsAdded() is applicable for argument types: () values: [])
and my closure and teardown method is defined as follows:
def deleteRowsAdded = {
while (driver.findElements(By.xpath(dataRowsSelector)).size() > initialRowCount) {
WebUI.callTestCase(findTestCase('DeleteStore'), [('shouldLogout') : true, ('shouldCloseBrowser') : true, ('loginAndCompanySelect') : true
, ('index') : initialRowCount], FailureHandling.STOP_ON_FAILURE)
}
}
#TearDown
def tearDown() {
deleteRowsAdded()
if (shouldLogout) {
WebUI.click(findTestObject('Object Repository/Page_Sign In/li_Sign Out'))
}
if (shouldCloseBrowser) {
WebUI.closeBrowser()
}
}
I have suite to run the regression Test Case in Soap UI. It has a Assertion Capture Response which measures the time of each request. This is needed on demand.
If metrics needed then I need to Enable the Capture Response Time assertion and if it is not needed then I don't need the capture response time.
I have written the below code to check that whether it is disabled or not. If it is disabled then OK else i need to disable it.
The following code returns
java.lang.NullPointerException: Cannot get property 'disabled' on null object.
Can any one help on this?
def project = testRunner.getTestCase().getTestSuite().getProject().getWorkspace().getProjectByName("Regression");
//Loop through each Test Suite in the project
for(suite in project.getTestSuiteList())
{
//log.info(suite.name)
//Loop through each Test Case
if(suite.name == "ReusableComponent")
{
for(tcase in suite.getTestCaseList())
{
log.info(tcase.name)
for(tstep in tcase.getTestStepList())
{
stepName = tstep.name
suiteName=suite.name
caseName=tcase.name
def testStep = testRunner.testCase.testSuite.project.testSuites["$suiteName"].testCases["$caseName"].getTestStepByName("$stepName")
log.info(testStep.getAssertionByName("CaptureResponseTime").disabled)
}
}
}
}
Below statement is causing NullPointerException:
log.info(testStep.getAssertionByName("CaptureResponseTime").disabled)
In order to avoid NPE, then change it to:
log.info(testStep.getAssertionByName("CaptureResponseTime").isDisabled)
If you need to disable the assertion, then use below statement:
testStep.getAssertionByName("CaptureResponseTime")?.disabled = true
Another input:
In order to get the project, do not use workspace.
Instead use:
def project = context.testCase.testSuite.project
I want to disable certain test cases based on the value of some test suite properties (i.e if the property IsActive1 = false, then testcase1 will be disabled).
I used this code at test suite setup script but got an error:
def testSuite = context.testCase.testSuite;
def totalTestCases = testSuite.getTestCases().size();
for(n in (0..totalTestCases-1)) {
if(testSuite.getTestCaseAt(n).name == "${#TestSuite#IsActive}"){
testSuite.getTestCaseAt(n).setDisabled(true)
}
}
How can I do that?
Here is how I would go to achieve this.
Assuming that there is a suite with test cases, namely TestCase1, TestCase2, TestCase3, TestCase4, TestCase5. Using this approach, it would be a simple change of the property value to include or exclude the test case name to be disable. I believe that this would be better to change things from one place(single property) instead of changing IsActive property for each test case. If you have more cases to handle this would be a burden (going to each case and modify true or false for IsActive)
Create a custom property at test suite level, say DISABLE_TESTS with value (comma separated list to disable) as TestCase1, TestCase5
Here is the Setup Script at Suite level which would achieve to selectively execute the test cases.
/**
* Test Suite Setup Script
* Enable or disable selected list of test cases
* Based on the test suite property DISABLE_TESTS value
**/
//Disables a Test case
def disableTestCase(testCaze) {
log.info "Disabling test case : ${testCaze.name}"
testCaze.disabled = true
}
//Enables a Test case
def enableTestCase(testCaze) {
log.info "Enabling test case : ${testCaze.name}"
testCaze.disabled = false
}
//Read the test case names to enable and convert it to list
def disableList = testSuite.getPropertyValue('DISABLE_TESTS')?.split(',')?.collect { it.trim()} ?: []
log.info "List of test for disable: ${disableList}"
//Loop thru the test cases and enable or disable
testSuite.testCaseList.each { kase ->
//If the above list contains test case name disable, enable otherwise
if (disableList && disableList.contains(kase.name)) {
disableTestCase(kase)
} else {
enableTestCase(kase)
}
}
Since some of the cases are disabled, it would be good to enable all the cases as part of Test Suite Teardown Script. It would look mostly same, but there wont be any condition.
/**
* Test Suite Teardown Script
* Which enables all the test cases after selective execution
**/
//Enables a Test case
def enableTestCase(testCaze) {
log.info "Enabling test case : ${testCaze.name}"
testCaze.disabled = false
}
//Loop thru the test cases and enable
testSuite.testCaseList.each { kase ->
enableTestCase(kase)
}
You can do that with a Groovy script. You could place this script in the Setup script tab on testSuite Window, in order that the script is executed before your testSuite, disabling/enabling testCases depending on the properties.
Based on your requeriments this script could be something like:
// get property names getting only
// the one which start with "isactive"
def isActiveList = testSuite.getPropertyNames().findAll {
it.toLowerCase().startsWith('isactive')
}
log.info isActiveList
// get testCaseList in order
def testCaseList = testSuite.getTestCaseList()
// for each "isactive" property
// enable or disable the corresponding
// testCase
isActiveList.each{ name ->
// get the value
def isActive = testSuite.getPropertyValue(name).toBoolean()
// get the order from the property name
def testCaseIndex = name.toLowerCase() - 'isactive'
log.info "testCase at index $testCaseIndex will be disabled ${!isActive}"
// get the testCase and enable/disable depend
// on isactive property
// NOTE: IsActive1 corresponds to array pos 0
// so a -1 is necessary
log.info testCaseList[testCaseIndex.toInteger()-1]?.disabled = !isActive
}
Maybe it's better to rename your properties based on the testCase name's to enable/disable instead of using a number; to avoid undesired behaviors if you change i.e the testCase order or add a new one...
Hope it helps,
I have a Groovy application that can be custimized by a small Groovy DSL I wrote. On startup, the application loads several Groovy scripts, applies some AST transformations and finally executes whatever was specified in the scripts.
One of the AST transformations inserts a couple of lines of code into certain methods. That works fine and I can see the different behavior during runtime. However, sometimes the generated code is not correct. Although I load the scripts with the TypeChecked customizer in place, my generated code is never checked for soundness.
To show my problem, I constructed an extreme example. I have the following script:
int test = 10
println test // prints 10 when executed without AST
I load this script and insert a new line of code between the declaration of test and println:
public void visitBlockStatement(BlockStatement block) {
def assignment = (new AstBuilder().buildFromSpec {
binary {
variable "test"
token "="
constant 15
}
}).first()
def newStmt = new ExpressionStatement(assignment)
newStmt.setSourcePosition(block.statements[1])
block.statements.add(2, newStmt)
super.visitBlockStatement(block)
}
After applying this AST, the script prints 15. When I use AstNodeToScriptVisitor to print the Groovy code of the resulting script, I can see the new assignment added to the code.
However, if I change the value of the assignment to a String value:
// ...
def assignment = (new AstBuilder().buildFromSpec {
binary {
variable "test"
token "="
constant "some value"
}
}).first()
// ...
I get a GroovyCastExcpetion at runtime. Although the resulting script looks like this:
int test = 10
test = "some value" // no compile error but a GroovyCastException at runtime here. WHY?
println test
no error is raised by TypeChecked. I read in this mailing list, that you need to set the source position for generated code to be checked, but I'm doing that an it still doesn't work. Can anyone provide some feedback of what I am doing wrong? Thank you very much!
Update
I call the AST by attaching it to the GroovyShell like this:
def config = new CompilerConfiguration()
config.addCompilationCustomizers(
new ASTTransformationCustomizer(TypeChecked)
)
config.addCompilationCustomizers(
new ASTTransformationCustomizer(new AddAssignmentAST())
)
def shell = new GroovyShell(config)
shell.evaluate(new File("./path/to/file.groovy"))
The class for the AST itself looks like this:
#GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
class AddAssignmentAST implements ASTTransformation {
#Override
public void visit(ASTNode[] nodes, SourceUnit source) {
def transformer = new AddAssignmentTransformer()
source.getAST().getStatementBlock().visit(transformer)
}
private class AddAssignmentTransformer extends CodeVisitorSupport {
#Override
public void visitBlockStatement(BlockStatement block) {
// already posted above
}
}
}
Since my Groovy script only consists of one block (for this small example) the visitBlockStatement method is called exactly once, adds the assignment (which I can verify since the output changes) but does not ever throw a compile-time error.