Katalon 7.9 => error "Caused by: java.lang.ClassFormatError: CustomKeywords"

Continuing the discussion from Katalon version 7.9.0: Caused by: java.lang.ClassFormatError: Illegal method name after running test suite:

Hello,
I have same error message than the one in preceding link.

here is my code which generate error :

String EdiFinalDeliveryDate = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyyyMMdd000000', 1, 0)

I tried another syntax as suggested in post, but it always generate same error on my line 28
CustomKeywords.test.common.TimeHelper.getServerTimestamp('yyyyMMdd000000', 1, 0)

Could you suggest me correct syntax in order to use in katalon 7.9 ?

here is complete error message :

2021-04-27 17:50:50.681 INFO c.k.k.c.c.k.CucumberBuiltinKeywords - Starting run keyword runFeatureFile: ‘Include/features/MySCM.feature’ and extract report to folder: ‘C:\Users\staniere\AppData\Local\Temp\Katalon\Include\features\MySCM.feature\20210427_175048/cucumber_report/1619538650672’…
2021-04-27 17:50:51.483 ERROR c.runtime.formatter.CucumberReporter - :x: SCENARIO MySCM1_2_3 - creation WCDCRE - Deactivation WCDANN - Reactivation WCDCRE FAILED.
Reason:
cucumber.runtime.CucumberException: Failed to instantiate class MySCM
at cucumber.runtime.java.DefaultJavaObjectFactory.cacheNewInstance(DefaultJavaObjectFactory.java:47)
at cucumber.runtime.java.DefaultJavaObjectFactory.getInstance(DefaultJavaObjectFactory.java:33)
at cucumber.runtime.java.JavaHookDefinition.execute(JavaHookDefinition.java:60)
at cucumber.runtime.HookDefinitionMatch.runStep(HookDefinitionMatch.java:14)
at cucumber.runner.TestStep.executeStep(TestStep.java:55)
at cucumber.runner.TestStep.run(TestStep.java:42)
at cucumber.runner.TestCase.run(TestCase.java:41)
at cucumber.runner.Runner.runPickle(Runner.java:44)
at cucumber.runtime.Runtime.runFeature(Runtime.java:120)
at cucumber.runtime.Runtime.run(Runtime.java:106)
at cucumber.api.cli.Main.run(Main.java:35)
at cucumber.api.cli.Main$run.call(Unknown Source)
at com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords$_runFeatureFile_closure1.doCall(CucumberBuiltinKeywords.groovy:106)
at com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords$_runFeatureFile_closure1.doCall(CucumberBuiltinKeywords.groovy)
at com.kms.katalon.core.keyword.internal.KeywordMain.runKeyword(KeywordMain.groovy:68)
at com.kms.katalon.core.keyword.internal.KeywordMain$runKeyword.call(Unknown Source)
at com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords.runFeatureFile(CucumberBuiltinKeywords.groovy:73)
at com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords$runFeatureFile$0.callStatic(Unknown Source)
at com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords.runFeatureFile(CucumberBuiltinKeywords.groovy:246)
at com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords$runFeatureFile.call(Unknown Source)
at WSVerification1619538650597.run(WSVerification1619538650597:2)
at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
at com.kms.katalon.core.main.WSVerificationExecutor.runScript(WSVerificationExecutor.java:178)
at com.kms.katalon.core.main.WSVerificationExecutor.doExecute(WSVerificationExecutor.java:172)
at com.kms.katalon.core.main.WSVerificationExecutor.processExecutionPhase(WSVerificationExecutor.java:155)
at com.kms.katalon.core.main.WSVerificationExecutor.accessMainPhase(WSVerificationExecutor.java:147)
at com.kms.katalon.core.main.WSVerificationExecutor.execute(WSVerificationExecutor.java:129)
at com.kms.katalon.core.main.TestCaseMain.runFeatureFile(TestCaseMain.java:144)
at com.kms.katalon.core.main.TestCaseMain$runFeatureFile$0.call(Unknown Source)
at TempTempCase1619538648431.run(TempTempCase1619538648431.groovy:25)
Caused by: java.lang.reflect.InvocationTargetException
at cucumber.runtime.java.DefaultJavaObjectFactory.cacheNewInstance(DefaultJavaObjectFactory.java:41)
… 30 more
Caused by: java.lang.ClassFormatError: Illegal method name “test.common.ReflexShare.getEDIinModeleSourceFilePath” in class CustomKeywords
at MySCM.(MySCM.groovy:28)
… 31 more

@spuygrenier , it could interest you also

As far as I can tell, this is not a continuation of that discussion.

It is hard to say what the cause of your problem is, since you haven’t shown much code.

You have misunderstood. That is not what was suggested. Again, I (we) need to see more of your code.

Hello,
yes, I could have put entire code.

Here is my MySCM.groovy file:

import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase

import com.kms.katalon.core.model.FailureHandling
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI

import cucumber.api.CucumberOptions
import cucumber.api.Scenario
import cucumber.api.java.After
import cucumber.api.java.Before;
import cucumber.api.java.en.And
import cucumber.api.java.en.Given
import cucumber.api.java.en.Then
import cucumber.api.java.en.When
import cucumber.api.junit.Cucumber

import java.nio.file.Files
import java.nio.file.Path as Path

import org.junit.runner.RunWith

@RunWith(Cucumber.class)
@CucumberOptions(features="Include/features",glue="", plugin=["pretty", "html:ReportsCucumber","json:ReportsCucumber/cucumber.json"])

class MySCM {
	/**
	 * The step definitions below match with Katalon sample Gherkin steps
	 */
	String EdiFinalDeliveryDate = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyyyMMdd000000', 1, 0)
	String finalDeliveryDate = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('ddMMyy', 1, 0)
	String EDIdeliveryDateHour = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyyyMMddHHmm', 1, 0)
	String EdiOdpDate = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyyyMMdd000000', 0, 0)
	String timestamp = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyMMdd-HHmm', 0, 0)
	String odpRef = "Katalon_" + timestamp
	String MinEdiSpid = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyMMdd=HHmmss00', 0, 0)

	String scenario_name
	String scenario_prefix

	@Before
	public void before(Scenario s) {
		scenario_name = s.getName()
		scenario_prefix = scenario_name.split(" ").first() //on extrait le debut du nom du scénario (ex : "MySCM1")
		System.out.println("@before currently executig scenario : " + scenario_name);

		// TODO Ajout étape dans report Katalon
		WebUI.comment("EXECUTION SCENARIO : "+scenario_name)
	}

	// bloc after pour récupérer snapshot si le test échoue
	// inspiré de https://stackoverflow.com/questions/56580340/screenshot-with-cucumber-groovy
	// et https://medium.com/@priyank.it/cucumber-report-taking-screenshot-embedding-inside-47d6d3c723bc

	@After
	public void tearDown(Scenario scenario) {
		println "teardown Tests cucumber"
		if(scenario.isFailed()) {
			println "teardown Tests cucumber isFailed"
			String filePath = WebUI.takeScreenshot()
			File file = new File(filePath)
			scenario.embed(Files.readAllBytes(file.toPath()), "image/png")
		}

	}

	/* ----------------- GIVEN -----------------*/
	@Given("I create PRO")
	def I_create_pro() {
		WebUI.callTestCase(findTestCase('ODP/ODP creation 1 ligne'), [('odpRef') : odpRef, ('finalDeliveryDate') : finalDeliveryDate
			, ('refArticle') : 'KAT0001'], FailureHandling.STOP_ON_FAILURE)
	}

	@Given("I create PRO with 2 lines")
	def I_create_pro_with_2_lines() {
		WebUI.callTestCase(findTestCase('ODP/ODP creation 2 lignes'), [('odpRef') : odpRef, ('finalDeliveryDate') : finalDeliveryDate
			, ('refArticle') : '21011103', ('refArticle2') : '21016174'], FailureHandling.STOP_ON_FAILURE)
	}

	@Given("I create PRO by interface with file (.*)")
	def I_create_pro_by_interface(String EDIfile) {
		def variablesToReplace = [('odpRef') : odpRef, ('dateLiv') : EDIdeliveryDateHour]

		Path EDI_in_file_COMPOSED = CustomKeywords.'test.common.ReflexShare.EDIgetComposedFile'(scenario_prefix, EDIfile, variablesToReplace)

		WebUI.callTestCase(findTestCase('EDI in injection/generic functions/EDI integrate message by HFQ300'), [('filePath') : EDI_in_file_COMPOSED.toString()
			, ('partner') : 'EPF', ('messageType') : '*EPF_0_CDE'], FailureHandling.STOP_ON_FAILURE)

	}


	/* ----------------- WHEN -----------------*/
	@When("I launch volume calculation")
	def I_launch_volume_calculation() {
		WebUI.callTestCase(findTestCase('ODP/ODP volume calculation'), [('odpRef') : odpRef], FailureHandling.STOP_ON_FAILURE)
	}

	@When("I launch PRO generation")
	def I_launch_odp_generation() {
		WebUI.callTestCase(findTestCase('ODP/ODP Generation'), [('odpRef') : odpRef, ('dateDaujourdhui') : ''], FailureHandling.STOP_ON_FAILURE)
	}

	@When("I re-activate PRO")
	def I_reactivate_odp() {
		WebUI.callTestCase(findTestCase('ODP/ODP re-activation'), [('odpRef') : odpRef], FailureHandling.STOP_ON_FAILURE)
	}

	@When("I deactivate PRO")
	def I_deactivate_odp() {
		WebUI.callTestCase(findTestCase('ODP/ODP cancelation'), [('odpRef') : odpRef], FailureHandling.STOP_ON_FAILURE)
	}

	@When("I launch preparation run")
	def I_launch_preparation_run() {
		WebUI.callTestCase(findTestCase('ODP/Preparation run'), [('odpRef') : odpRef], FailureHandling.STOP_ON_FAILURE)
	}

	@When("I launch preparation validation")
	def I_launch_preparation_validation() {
		WebUI.callTestCase(findTestCase('ODP/Preparation validation'), [('odpRef') : odpRef], FailureHandling.STOP_ON_FAILURE)
	}

	@When("I assign preparation to loading")
	def I_assign_preparation_to_load() {
		String Datedujour = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('ddMMyy', 0, 0)
		String loadingCode = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('HHmmss', 0, 0)
		String loadingDes = 'Kat Cha_' + loadingCode

		WebUI.callTestCase(findTestCase('Load/Load Creation'), [('loadingDate') : Datedujour, ('loadingCode') : loadingCode, ('loadingDes') : loadingDes],
		FailureHandling.STOP_ON_FAILURE)

		WebUI.callTestCase(findTestCase('Load/Load Assignation to prep'), [('loadingDate') : Datedujour, ('loadingCode') : loadingCode
			, ('refOdp') : odpRef], FailureHandling.STOP_ON_FAILURE)
	}

	@When("I close preparation run")
	def I_close_preparation_run() {
		WebUI.callTestCase(findTestCase('ODP/Preparation Run for close'), [('odpRef') : odpRef], FailureHandling.STOP_ON_FAILURE)
	}

	/* ----------------- AND -----------------*/
	@And("I trigger MySCM export within GTS")
	def I_trigger_myscm_export_within_GTS() {
		MinEdiSpid = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyMMdd=HHmmss00', 0, 0)
		WebUI.callTestCase(findTestCase('EDI check/GTS start-stop agent by name'), [('agent_name') : 'E_SCM - EPF'], FailureHandling.STOP_ON_FAILURE)
	}

	/* ----------------- THEN -----------------*/
	@Then("I verify I get MySCM1 export file which contains WCDCRE")
	def I_verify_i_get_myscm1() {
		WebUI.callTestCase(findTestCase('EDI check/EDI check MySCM 1 PRO Creation'), [('MinEdiSpid') : MinEdiSpid, ('odpRef') : odpRef
			, ('EdiFinalDeliveryDate') : EdiFinalDeliveryDate, ('EdiOdpDate') : EdiOdpDate], FailureHandling.STOP_ON_FAILURE)
	}

	@Then("I verify export file contains ACTE (.*)")
	def I_verify_myscm_export_file_contains(String acte) {
		System.out.println("@contains ACTE : currently executig scenario " + scenario_name);
		CustomKeywords.'test.common.ReflexShare.EdiCheckMyScmActes'(MinEdiSpid, odpRef, acte, scenario_prefix)
	}

	@Then("I compare export file to template SCM4")
	def I_compare_export_file_to_template_scm4() {
		WebUI.callTestCase(findTestCase('EDI check/EDI check MySCM 4 PRO Generation'), [('MinEdiSpid') : MinEdiSpid, ('odpRef') : odpRef
			, ('EdiFinalDeliveryDate') : EdiFinalDeliveryDate, ('EdiOdpDate') : EdiOdpDate], FailureHandling.STOP_ON_FAILURE)
	}

	@Then("I compare export file to template SCM5")
	def I_compare_export_file_to_template_scm5() {
		WebUI.callTestCase(findTestCase('EDI check/EDI check MySCM 5 Pick Run'), [('MinEdiSpid') : MinEdiSpid, ('odpRef') : odpRef
			, ('EdiFinalDeliveryDate') : EdiFinalDeliveryDate, ('EdiOdpDate') : EdiOdpDate], FailureHandling.STOP_ON_FAILURE)
	}

	@Then("I compare export file to template SCM6")
	def I_compare_export_file_to_template_scm6() {
		WebUI.callTestCase(findTestCase('EDI check/EDI check MySCM 6 Preparation Validation'), [('MinEdiSpid') : MinEdiSpid, ('odpRef') : odpRef
			, ('EdiFinalDeliveryDate') : EdiFinalDeliveryDate, ('EdiOdpDate') : EdiOdpDate], FailureHandling.STOP_ON_FAILURE)
	}

	@Then("I compare export file to template SCM7")
	def I_compare_export_file_to_template_scm7() {
		WebUI.callTestCase(findTestCase('EDI check/EDI check MySCM 9 Preparation Closure P'), [('MinEdiSpid') : MinEdiSpid, ('odpRef') : odpRef
			, ('EdiFinalDeliveryDate') : EdiFinalDeliveryDate, ('EdiOdpDate') : EdiOdpDate], FailureHandling.STOP_ON_FAILURE)
	}

	@Then("I compare export file to template SCM8")
	def I_compare_export_file_to_template_scm8() {
		WebUI.callTestCase(findTestCase('EDI check/EDI check MySCM 8 Preparation Closure T'), [('MinEdiSpid') : MinEdiSpid, ('odpRef') : odpRef
			, ('EdiFinalDeliveryDate') : EdiFinalDeliveryDate, ('EdiOdpDate') : EdiOdpDate], FailureHandling.STOP_ON_FAILURE)
	}




}

one another code which could be interesting is my Libs\CustomKeywords.groovy :
Indeed, first line call getEDIinModeleSourceFilePath which is included in error message.

/**

  • This class is generated automatically by Katalon Studio and should not be modified or deleted.
    */

import java.lang.String

import java.nio.file.Path

import java.util.Map

import com.applitools.eyes.selenium.Eyes

import org.openqa.selenium.WebElement

import com.kms.katalon.core.testobject.TestObject

import com.kms.katalon.core.model.FailureHandling

import java.util.List

import kms.turing.katalon.plugins.helper.table.WebTableHelper.CellTextOptions

import kms.turing.katalon.plugins.helper.XPathHelper.CompareOptions

import com.applitools.eyes.RectangleSize

def static “test.common.ReflexShare.getEDIinModeleSourceFilePath”(
String testName ) {
(new test.common.ReflexShare()).getEDIinModeleSourceFilePath(
testName)
}

def static “test.common.ReflexShare.getEDIoutModeleSourceFilePath”(
String testName ) {
(new test.common.ReflexShare()).getEDIoutModeleSourceFilePath(
testName)
}

def static “test.common.ReflexShare.getReportFolderPath”() {
(new test.common.ReflexShare()).getReportFolderPath()
}

/**

  • Compare 2 fichiers
  • extrait les champs ayant une différence
  • @param ORIGINAL_path
  • @param REVISED_path
  • @return
    */
    def static “test.common.ReflexShare.EDIcompareFiles”(
    Path ORIGINAL_path
    , Path REVISED_path
    , Map dynamic_variables ) {
    (new test.common.ReflexShare()).EDIcompareFiles(
    ORIGINAL_path
    , REVISED_path
    , dynamic_variables)
    }

/**

  • récupère le fichier template dans “Data Files\EDI out”, le copie dans le dossier report, le nettoie pour le rendre comparable,
  • @param filename
  • @return renvoie le Path du fichier “comparable”
    */
    def static “test.common.ReflexShare.EDIgetComparableTemplateFile”(
    String testName ) {
    (new test.common.ReflexShare()).EDIgetComparableTemplateFile(
    testName)
    }

/**
*

  • @param testName nom du test (pour nommer le fichier avec ce nom)
  • @param EDI_in_template_filename fichier template EDI
  • @param variablesToReplace variables à remplacer dans le fichier template
  • @return
    */
    def static “test.common.ReflexShare.EDIgetComposedFile”(
    String testName
    , String EDI_in_template_filename
    , Map variablesToReplace
    , boolean add_spaces_to_field ) {
    (new test.common.ReflexShare()).EDIgetComposedFile(
    testName
    , EDI_in_template_filename
    , variablesToReplace
    , add_spaces_to_field)
    }

/**

  • Copie le fichier dans reflexShare (et renvoie en resultat le début du fichier)
  • @param fileToIntegrate chemin du fichier à copier
  • @param reflexShareFolder chemin du dossier reflexShare dans lequel copier le fichier
  • @return 51 premiers caractères du fichier (pour utilisation dans TestCase ‘EDI check/EDI integration check’)
    */
    def static “test.common.ReflexShare.EDIintegrateMessage”(
    Path fileToIntegrate
    , String reflexShareFolder ) {
    (new test.common.ReflexShare()).EDIintegrateMessage(
    fileToIntegrate
    , reflexShareFolder)
    }

/**

  • récupère le fichier test dans ReflexShare, le copie dans le dossier report, le nettoie pour le rendre comparable, le tronque pour ne sortir qu’un bloc ENT contenant le numODP
  • @param folder dossier dans reflexShare
  • @param inicli prefixe du fichier à rechercher
  • @param MinEdiSpid Spid minimum théorique du fichier (pour ne renvoyer que les fichiers générés après test)
  • @param numODP numéro ODP afin de pouvoir récupérer le bon bloc ENT
  • @return
    */
    def static “test.common.ReflexShare.EDIgetComparableTestFile”(
    String testName
    , String folder
    , String inicli
    , String MinEdiSpid
    , String numODP ) {
    (new test.common.ReflexShare()).EDIgetComparableTestFile(
    testName
    , folder
    , inicli
    , MinEdiSpid
    , numODP)
    }

/**

  • renvoie la date courante au format milliseconde
  • pour utilisation avec fonction getLastFile()
  • @return date courante en millisecondes
    */
    def static “test.common.ReflexShare.getMinLastModified”() {
    (new test.common.ReflexShare()).getMinLastModified()
    }

/**

  • renvoie le fichier le plus récent du dossier dont la date est supérieure à MinLastModified
  • @param reflexShareFolder
  • @param wildcardFileFilter format du fichier recherché (du type “FMPVD*.pdf” ou “FMCG72*.SPO”)
  • @param MinLastModified date minimum de création du fichier pour ne pas prendre en compte les anciennes editions (à générer avec getMinLastModified () )
  • @return
    */
    def static “test.common.ReflexShare.getLastFile”(
    String reflexShareFolder
    , String wildcardFileFilter
    , long MinLastModified
    , int timeout_recherche_fichier ) {
    (new test.common.ReflexShare()).getLastFile(
    reflexShareFolder
    , wildcardFileFilter
    , MinLastModified
    , timeout_recherche_fichier)
    }

def static “test.common.ReflexShare.getPdfText”(
Path pdfFile ) {
(new test.common.ReflexShare()).getPdfText(
pdfFile)
}

def static “test.common.ReflexShare.EDIgetLastFile”(
String folder
, String inicli
, String MinEdiSpid ) {
(new test.common.ReflexShare()).EDIgetLastFile(
folder
, inicli
, MinEdiSpid)
}

def static “test.common.ReflexShare.EDIselectENTbloc”(
String numODP
, String file_content
, Path target_file_path ) {
(new test.common.ReflexShare()).EDIselectENTbloc(
numODP
, file_content
, target_file_path)
}

def static “test.common.ReflexShare.EDIcleanFixedColumns”(
String file_content
, Path target_file_path ) {
(new test.common.ReflexShare()).EDIcleanFixedColumns(
file_content
, target_file_path)
}

def static “test.common.ReflexShare.regex_find”(
String regex
, String file_content ) {
(new test.common.ReflexShare()).regex_find(
regex
, file_content)
}

def static “test.common.ReflexShare.regex_substr”(
String regex
, String subst_txt
, String file_content ) {
(new test.common.ReflexShare()).regex_substr(
regex
, subst_txt
, file_content)
}

def static “test.common.ReflexShare.decompressGZIP”(
Path input
, Path outputDir ) {
(new test.common.ReflexShare()).decompressGZIP(
input
, outputDir)
}

def static “test.common.ReflexShare.getFileContent”(
Path path ) {
(new test.common.ReflexShare()).getFileContent(
path)
}

def static “test.common.ReflexShare.deleteLineFromFile”(
Path path
, String regex ) {
(new test.common.ReflexShare()).deleteLineFromFile(
path
, regex)
}

def static “test.common.ReflexShare.cleanEdiFile”(
String[] regex ) {
(new test.common.ReflexShare()).cleanEdiFile(
regex)
}

def static “test.common.ReflexShare.EdiCheckMyScmActes”(
String MinEdiSpid
, String odpRef
, String acte
, String scenario_prefix ) {
(new test.common.ReflexShare()).EdiCheckMyScmActes(
MinEdiSpid
, odpRef
, acte
, scenario_prefix)
}

def static “test.common.ReflexShare.EDIgetComposedFile”(
String testName
, String EDI_in_template_filename
, Map variablesToReplace ) {
(new test.common.ReflexShare()).EDIgetComposedFile(
testName
, EDI_in_template_filename
, variablesToReplace)
}

def static “test.common.ReflexShare.EdiCheckMyScmActes”(
String MinEdiSpid
, String odpRef
, String acte ) {
(new test.common.ReflexShare()).EdiCheckMyScmActes(
MinEdiSpid
, odpRef
, acte)
}

/**

  • Connexion à BDD Oracle du serveur reflex
  • se sert des variables du profil
  • @return
    */
    def static “test.common.DBHandler.connectOracleDB”() {
    (new test.common.DBHandler()).connectOracleDB()
    }

def static “test.common.DBHandler.executeQuery”(
String queryString ) {
(new test.common.DBHandler()).executeQuery(
queryString)
}

def static “test.common.DBHandler.closeDatabaseConnection”() {
(new test.common.DBHandler()).closeDatabaseConnection()
}

/**

  • Execute non-query (usually INSERT/UPDATE/DELETE/COUNT/SUM…) on database
  • @param queryString a SQL statement
  • @return single value result of SQL statement
    */
    def static “test.common.DBHandler.execute”(
    String queryString ) {
    (new test.common.DBHandler()).execute(
    queryString)
    }

/**

  • renvoie l’IC d’un odp
  • @param refOdp
  • @return IC
    */
    def static “test.common.DBHandler.getOdpIc”(
    String refOdp ) {
    (new test.common.DBHandler()).getOdpIc(
    refOdp)
    }

/**

  • renvoie le numéro d’année oenann et le numéro d’odp oenodp d’une ref odp
  • @param refOdp
  • @return une Map contenant oenann & oenodp
    */
    def static “test.common.DBHandler.getnumAnnOdpByRefOdp”(
    String refOdp ) {
    (new test.common.DBHandler()).getnumAnnOdpByRefOdp(
    refOdp)
    }

/**

  • renvoie le sscc (unique) de la mission de degerbage d’un ODP : ne fonctionne qu’avec un odp ayant une mission et un sscc
  • @param refOdp
  • @return sscc
    */
    def static “test.common.DBHandler.getSsccByRefOdp”(
    String refOdp ) {
    (new test.common.DBHandler()).getSsccByRefOdp(
    refOdp)
    }

/**

  • recherche le commentaire du sscc
  • @param sscc
  • @return commentaire
    */
    def static “test.common.DBHandler.getSsccComments”(
    String sscc
    , String group ) {
    (new test.common.DBHandler()).getSsccComments(
    sscc
    , group)
    }

/**

  • fait des SELECT toutes les secondes jusqu’à obtenir un commentaire non null (abandonne s’il atteint le timeout)
  • @param sscc
  • @param group
  • @param timeout
  • @return
    */
    def static “test.common.DBHandler.getSsccComments”(
    String sscc
    , String group
    , int timeout ) {
    (new test.common.DBHandler()).getSsccComments(
    sscc
    , group
    , timeout)
    }

/**

  • recherche le code motif de blocage d’un GEI (GECMBG) par son numéro de support (sscc)
  • @param sscc
  • @return code motif de blocage ( IPG hold code )
    */
    def static “test.common.DBHandler.getGeiHoldCode”(
    String sscc ) {
    (new test.common.DBHandler()).getGeiHoldCode(
    sscc)
    }

/**

  • cherche le nombre de palettes disponibles en stock pour un article
  • @param refArt
  • @return nombre de palettes dispo (sans prelevement non validé ni quantité déjà servie)
    */
    def static “test.common.DBHandler.getNbGeiDispo”(
    String refArt ) {
    (new test.common.DBHandler()).getNbGeiDispo(
    refArt)
    }

/**

  • renvoie une ref suffixée avec timestamp pour qu’elle soit unique (pour ref ODP par exemple)
  • @param prefix prefixe du test
  • @return la ref unique
    */
    def static “test.common.TimeHelper.generateRefOdp”(
    String prefix ) {
    (new test.common.TimeHelper()).generateRefOdp(
    prefix)
    }

/**

  • renvoie un timestamp Fr de la date du serveur
  • @param pattern (du type “dd-MM-yyyy” ou “HH:mm:ss”)
  • @param day_to_add permet d’ajout/retrancher des jours à la date actuelle
  • @param hour_to_add permet d’ajout/retrancher des heures à la date actuelle
  • @return le timetstamp au format correspondant à @pattern
    */
    def static “test.common.TimeHelper.getServerTimestamp”(
    String pattern
    , int day_to_add
    , int hour_to_add ) {
    (new test.common.TimeHelper()).getServerTimestamp(
    pattern
    , day_to_add
    , hour_to_add)
    }

/**
*

  • @return le timetstamp codé sur 6 digits
    */
    def static “test.common.TimeHelper.getServerTimestampReducedDigits”() {
    (new test.common.TimeHelper()).getServerTimestampReducedDigits()
    }

def static “test.common.TimeHelper.addGlobalVariable”(
String name
, Object value ) {
(new test.common.TimeHelper()).addGlobalVariable(
name
, value)
}

def static “test.common.TimeHelper.startTimer”() {
(new test.common.TimeHelper()).startTimer()
}

def static “test.common.TimeHelper.stopTimer”(
String timerName ) {
(new test.common.TimeHelper()).stopTimer(
timerName)
}

def static “test.common.TimeHelper.writeJunitReport”(
String name
, String time ) {
(new test.common.TimeHelper()).writeJunitReport(
name
, time)
}

def static “test.common.TimeHelper.failTestAndGenerateJunitReport”(
String name ) {
(new test.common.TimeHelper()).failTestAndGenerateJunitReport(
name)
}

def static “com.kms.katalon.keyword.applitools.BasicKeywords.checkElement”(
Eyes eyes
, WebElement element ) {
(new com.kms.katalon.keyword.applitools.BasicKeywords()).checkElement(
eyes
, element)
}

def static “com.kms.katalon.keyword.applitools.BasicKeywords.checkTestObject”(
TestObject testObject
, String testName ) {
(new com.kms.katalon.keyword.applitools.BasicKeywords()).checkTestObject(
testObject
, testName)
}

def static “com.kms.katalon.keyword.applitools.BasicKeywords.checkWindow”(
String testName ) {
(new com.kms.katalon.keyword.applitools.BasicKeywords()).checkWindow(
testName)
}

/**

  • click amélioré pour éviter exceptions StaleElementReferenceException && ElementNotVisibleException && ElementNotInteractableException
    */
    def static “test.common.FmUI.fmClick”(
    TestObject testObject
    , FailureHandling failureHandling ) {
    (new test.common.FmUI()).fmClick(
    testObject
    , failureHandling)
    }

/**
*

  • @param testObject
    */
    def static “test.common.FmUI.fmClick”(
    TestObject testObject ) {
    (new test.common.FmUI()).fmClick(
    testObject)
    }

/**

  • fonction pour rafraichir une page tant qu’on ne trouve pas une icone
    */
    def static “test.common.FmUI.waitForIcon”(
    TestObject icon_to_wait
    , TestObject refresh_button
    , int timeout_in_seconds ) {
    (new test.common.FmUI()).waitForIcon(
    icon_to_wait
    , refresh_button
    , timeout_in_seconds)
    }

/**

  • ferme les fenêtres jusqu’à trouver celle que l’on recherche (par son titre)
  • @param screenTitle titre de l’écran recherché (‘HFOE01’ par exemple)
  • @return true si ecran trouvé, false dans l’autre cas
    */
    def static “test.common.FmUI.findAlreadyOpenScreen”(
    String screenTitle ) {
    (new test.common.FmUI()).findAlreadyOpenScreen(
    screenTitle)
    }

def static “test.common.ScreenshotDriver.takeObjectImage”(
TestObject testObject ) {
(new test.common.ScreenshotDriver()).takeObjectImage(
testObject)
}

def static “test.common.ScreenshotDriver.saveObjectImage”(
TestObject testObject
, String folder
, String filename ) {
(new test.common.ScreenshotDriver()).saveObjectImage(
testObject
, folder
, filename)
}

def static “test.common.ScreenshotDriver.checkSnapshotOfObject”(
TestObject objectToCheck
, String folder
, String expectedImageFile ) {
(new test.common.ScreenshotDriver()).checkSnapshotOfObject(
objectToCheck
, folder
, expectedImageFile)
}

def static “test.common.ScreenshotDriver.findImageName”(
TestObject objectToSnapshot
, String expectedImages_folder ) {
(new test.common.ScreenshotDriver()).findImageName(
objectToSnapshot
, expectedImages_folder)
}

def static “com.kazurayam.ksbackyard.HighlightElement.on”(
TestObject testObject ) {
(new com.kazurayam.ksbackyard.HighlightElement()).on(
testObject)
}

/**

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.identifyCellByValueAndColHeader”(
WebElement table
, String columnHeader
, String cellValue ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).identifyCellByValueAndColHeader(
table
, columnHeader
, cellValue)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.identifyCellByValueAndColHeader”(
WebElement table
, String columnHeader
, String cellValue
, FailureHandling flowControl ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).identifyCellByValueAndColHeader(
table
, columnHeader
, cellValue
, flowControl)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.identifyTableByColumnHeaders”(
java.util.List columnHeaders
, int timeout ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).identifyTableByColumnHeaders(
columnHeaders
, timeout)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.identifyTableByColumnHeaders”(
java.util.List columnHeaders ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).identifyTableByColumnHeaders(
columnHeaders)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.identifyTableByColumnHeaders”(
java.util.List columnHeaders
, int timeout
, FailureHandling flowControl ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).identifyTableByColumnHeaders(
columnHeaders
, timeout
, flowControl)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.getColumnIndexByAttribute”(
WebElement table
, String attribute
, String value ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).getColumnIndexByAttribute(
table
, attribute
, value)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.getColumnIndexByAttribute”(
WebElement table
, String attribute
, String value
, FailureHandling flowControl ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).getColumnIndexByAttribute(
table
, attribute
, value
, flowControl)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.getColumnIndexByHeader”(
WebElement table
, String columnHeader
, FailureHandling flowControl ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).getColumnIndexByHeader(
table
, columnHeader
, flowControl)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.getColumnIndexByHeader”(
WebElement table
, String columnHeader ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).getColumnIndexByHeader(
table
, columnHeader)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.getRowIndexByCellsInfo”(
WebElement table
, Map cellsInfo
, FailureHandling flowControl ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).getRowIndexByCellsInfo(
table
, cellsInfo
, flowControl)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.getRowIndexByCellsInfo”(
WebElement table
, Map cellsInfo ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).getRowIndexByCellsInfo(
table
, cellsInfo)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.identifyCellByHeaderAndCellsInfo”(
WebElement table
, String columnHeader
, Map cellsInfo ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).identifyCellByHeaderAndCellsInfo(
table
, columnHeader
, cellsInfo)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.identifyCellByHeaderAndCellsInfo”(
WebElement table
, String columnHeader
, Map cellsInfo
, FailureHandling flowControl ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).identifyCellByHeaderAndCellsInfo(
table
, columnHeader
, cellsInfo
, flowControl)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.identifyCellByIndexes”(
WebElement table
, int columnIndex
, int rowIndex
, FailureHandling flowControl ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).identifyCellByIndexes(
table
, columnIndex
, rowIndex
, flowControl)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.identifyCellByIndexes”(
WebElement table
, int columnIndex
, int rowIndex ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).identifyCellByIndexes(
table
, columnIndex
, rowIndex)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.verifyRowDisplayed”(
WebElement table
, Map cellsInfo
, FailureHandling flowControl ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).verifyRowDisplayed(
table
, cellsInfo
, flowControl)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.verifyRowDisplayed”(
WebElement table
, Map cellsInfo ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).verifyRowDisplayed(
table
, cellsInfo)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.verifyCellPresentWithText”(
WebElement table
, String columnHeader
, String text
, CellTextOptions textOption
, CompareOptions compareOption ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).verifyCellPresentWithText(
table
, columnHeader
, text
, textOption
, compareOption)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.verifyCellPresentWithText”(
WebElement table
, String columnHeader
, String text
, CellTextOptions textOption ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).verifyCellPresentWithText(
table
, columnHeader
, text
, textOption)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.verifyCellPresentWithText”(
WebElement table
, String columnHeader
, String text ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).verifyCellPresentWithText(
table
, columnHeader
, text)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.verifyCellPresentWithText”(
WebElement table
, String columnHeader
, String text
, CellTextOptions textOption
, CompareOptions compareOption
, FailureHandling flowControl ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).verifyCellPresentWithText(
table
, columnHeader
, text
, textOption
, compareOption
, flowControl)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.getCellsValueByColumnHeader”(
WebElement table
, String columnHeader ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).getCellsValueByColumnHeader(
table
, columnHeader)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.getCellsValueByColumnHeader”(
WebElement table
, String columnHeader
, FailureHandling flowControl ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).getCellsValueByColumnHeader(
table
, columnHeader
, flowControl)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.clickOnColumn”(
WebElement table
, String columnHeader ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).clickOnColumn(
table
, columnHeader)
}

def static “kms.turing.katalon.plugins.helper.table.HTMLTableHelper.clickOnColumn”(
WebElement table
, String columnHeader
, FailureHandling flowControl ) {
(new kms.turing.katalon.plugins.helper.table.HTMLTableHelper()).clickOnColumn(
table
, columnHeader
, flowControl)
}

def static “com.kms.katalon.keyword.applitools.EyesKeywords.eyesOpen”(
String testName
, RectangleSize viewportSize ) {
(new com.kms.katalon.keyword.applitools.EyesKeywords()).eyesOpen(
testName
, viewportSize)
}

def static “com.kms.katalon.keyword.applitools.EyesKeywords.eyesClose”(
Eyes eyes ) {
(new com.kms.katalon.keyword.applitools.EyesKeywords()).eyesClose(
eyes)
}

def static “com.kms.katalon.keyword.applitools.EyesKeywords.eyesInit”() {
(new com.kms.katalon.keyword.applitools.EyesKeywords()).eyesInit()
}

def static “com.kms.katalon.keyword.applitools.EyesKeywords.eyesOpenWithBaseline”(
String baselineName
, String testName
, RectangleSize viewportSize ) {
(new com.kms.katalon.keyword.applitools.EyesKeywords()).eyesOpenWithBaseline(
baselineName
, testName
, viewportSize)
}

Hello @Russ_Thomas, no idea about this ?
perhaps did I not send usefull files

this error is really Strange as in error message, problem is launched from MySCM.groovy:28 which is trigering Illegal method name “test.common.ReflexShare.getEDIinModeleSourceFilePath” in class CustomKeywords :

	at com.kms.katalon.core.main.TestCaseMain$runFeatureFile$0.call(Unknown Source)
	at TempTempCase1620118194141.run(TempTempCase1620118194141.groovy:25)
Caused by: java.lang.reflect.InvocationTargetException
	at cucumber.runtime.java.DefaultJavaObjectFactory.cacheNewInstance(DefaultJavaObjectFactory.java:41)
	... 30 more
Caused by: java.lang.ClassFormatError: Illegal method name "test.common.ReflexShare.getEDIinModeleSourceFilePath" in class CustomKeywords
	at MySCM.<init>(MySCM.groovy:28)
	... 31 more

but this class MySCM is calling another CustomKeyword test.common.TimeHelper which is not in the same class that in the error message test.common.ReflexShare :woozy_face:

class MySCM {
	/**
	 * The step definitions below match with Katalon sample Gherkin steps
	 */
	String EdiFinalDeliveryDate = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyyyMMdd000000', 1, 0)

It seem that this error is launched when instantiating every CustomKeywords classes (before launching test.common.TimeHelper.getServerTimestamp() )

I uploaded my 2 classes from \katalonreflexcore\Keywords\test\common :
common.zip (10.0 KB)

Hopping it could be usefull to help me !

@staniere

Please try

  1. close KS
  2. remove projectDir/bin and projectDir/Libs
  3. restart KS, reopen the project

This will ensure all of your source codes are cleanly compiled to .class files. I hope mysterious Exceptions like java.lang.ClassFormatError will disappear.

unfortunately, this tip did not have big effect

only change is that this error does not occur in same CustomKeywords class
this time “Illegal method name” concerns “test.common.ScreenshotDriver.takeObjectImage” instead of “test.common.ReflexShare.getEDIinModeleSourceFilePath”

2021-05-06 17:44:26.068 ERROR c.runtime.formatter.CucumberReporter     - ❌ SCENARIO PCC preparation - one palette - T4 (API Preparation) FAILED.
Reason:
cucumber.runtime.CucumberException: Failed to instantiate class MySCM
	at cucumber.runtime.java.DefaultJavaObjectFactory.cacheNewInstance(DefaultJavaObjectFactory.java:47)
	at cucumber.runtime.java.DefaultJavaObjectFactory.getInstance(DefaultJavaObjectFactory.java:33)
	at cucumber.runtime.java.JavaHookDefinition.execute(JavaHookDefinition.java:60)
.................................
	at com.kms.katalon.core.main.TestCaseMain$runFeatureFile$0.call(Unknown Source)
	at TempTempCase1620314420846.run(TempTempCase1620314420846.groovy:25)
Caused by: java.lang.reflect.InvocationTargetException
	at cucumber.runtime.java.DefaultJavaObjectFactory.cacheNewInstance(DefaultJavaObjectFactory.java:41)
	... 30 more
Caused by: java.lang.ClassFormatError: Illegal method name "test.common.ScreenshotDriver.takeObjectImage" in class CustomKeywords
	at MySCM.<init>(MySCM.groovy:28)
	... 31 more

Here is code of this class which looks good to me :

// code récupéré sur ce forum : https://forum.katalon.com/t/taking-screenshot-of-a-selected-webelement/13567
package test.common

import java.awt.image.BufferedImage
import java.nio.file.DirectoryStream
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths

import javax.imageio.ImageIO

import org.openqa.selenium.WebDriver
import org.openqa.selenium.WebElement

import com.kms.katalon.core.annotation.Keyword
import com.kms.katalon.core.configuration.RunConfiguration
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webui.common.WebUiCommonHelper as WebUiCommonHelper
import com.kms.katalon.core.webui.driver.DriverFactory

import ru.yandex.qatools.ashot.AShot
import ru.yandex.qatools.ashot.Screenshot
import ru.yandex.qatools.ashot.comparison.ImageDiff;
import ru.yandex.qatools.ashot.comparison.ImageDiffer;
import ru.yandex.qatools.ashot.coordinates.WebDriverCoordsProvider

public class ScreenshotDriver {

	@Keyword
	static BufferedImage takeObjectImage(TestObject testObject) {
		WebElement webElement = WebUiCommonHelper.findWebElement(testObject, 10)
		return takeElementImage(webElement)
	}

	@Keyword
	/**
	 * Enregistre un snapshot de l'objet (dans le dossier images)
	 * exemple d'utilisation : saveObjectImage(monIcone, "snapshots", "monIcone.png") 
	 * @param testObject
	 * @param folder
	 * @param filename
	 */
	void saveObjectImage(TestObject testObject, String folder, String filename) {
		WebElement webElement = WebUiCommonHelper.findWebElement(testObject, 10)
		saveElementImage(webElement, folder, filename)
	}

	// @Keyword
	static BufferedImage takeElementImage(WebElement webElement) {
		WebDriver webDriver = DriverFactory.getWebDriver()
		Screenshot screenshot = new AShot().
				coordsProvider(new WebDriverCoordsProvider()).
				takeScreenshot(webDriver, webElement)
		return screenshot.getImage()
	}

	// @Keyword
	void saveElementImage(WebElement webElement, String folder, String filename) {
		Path projectDir = Paths.get(RunConfiguration.getProjectDir())
		Path tmpDir = projectDir.resolve("images/"+folder)
		Path pngFile = tmpDir.resolve(filename)

		WebDriver webDriver = DriverFactory.getWebDriver()
		if (!Files.exists(pngFile.getParent())) {
			Files.createDirectories(pngFile.getParent())
		}
		BufferedImage image = takeElementImage(webElement)
		ImageIO.write(image, "PNG", pngFile.toFile())
	}

	@Keyword
	// TODO : String findImageModel(TestObject objectToCheck, String folder)
	// renvoie le nom du fichier qui "matche" avec le snapshot
	boolean checkSnapshotOfObject (TestObject objectToCheck, String folder, String expectedImageFile) {
		Path projectDir = Paths.get(RunConfiguration.getProjectDir())
		Path tmpDir = projectDir.resolve("images/"+folder)
		Path expectedFile = tmpDir.resolve(expectedImageFile)

		BufferedImage expectedImage = ImageIO.read(expectedFile.toFile());
		BufferedImage currentSnapshot = takeObjectImage(objectToCheck)
		ImageDiffer imgDiff = new ImageDiffer();
		ImageDiff diff = imgDiff.makeDiff(currentSnapshot, expectedImage);
		return !diff.hasDiff()

	}

	@Keyword
	// TODO : String findImageModel(TestObject objectToCheck, String folder)
	// renvoie le nom du fichier qui "matche" avec le snapshot
	/**
	 * renvoie le nom du fichier qui "matche" avec le snapshot
	 * @param objectToSnapshot objet dont on veut trouver une correspondance
	 * @param expectedImages_folder dossier contenant les images à comparer
	 * @return renvoie le nom de l'image qui "matche" avec le snapshot
	 */
	String findImageName (TestObject objectToSnapshot, String expectedImages_folder) {
		Path projectDir = Paths.get(RunConfiguration.getProjectDir())
		Path tmpDir = projectDir.resolve("images/"+expectedImages_folder)


		BufferedImage currentSnapshot = takeObjectImage(objectToSnapshot)


		//File dossier = new File(tmpDir)
		//ListIterator<File> fichiers = Files.list(dossier).iterator()
		DirectoryStream<Path> stream = Files.newDirectoryStream(tmpDir);
		String result = null
		try {
			Iterator<Path> iterator = stream.iterator();
			while(iterator.hasNext() && result==null) {
				ImageDiffer imgDiff = new ImageDiffer();

				Path fichier = iterator.next();
				println fichier
				BufferedImage expectedImage = ImageIO.read(fichier.toFile())
				ImageDiff diff = imgDiff.makeDiff(currentSnapshot, expectedImage)

				if (!diff.hasDiff()) {
					result = fichier.getFileName()
					println "fichier trouvé ! result=" +result
				}
				/*
				 else {
				 println "fichier différent " +diff.hashCode()
				 BufferedImage diffImage = diff.getDiffImage();
				 File sauv_diff = new File(fichier.toString()+".diff.png")
				 println "fichier  " +sauv_diff
				 ImageIO.write(diff.getMarkedImage(),"PNG", sauv_diff);
				 }
				 */
			}
		} finally {
			stream.close();
		}

		if (result==null) result="INCONNU !"

		return result
	}
}

You showed your Include/scripts/groovy/MySCM.groovy file:

...
import org.junit.runner.RunWith

@RunWith(Cucumber.class)
@CucumberOptions(features="Include/features",glue="", plugin=["pretty", "html:ReportsCucumber","json:ReportsCucumber/cucumber.json"])

class MySCM {
	/**
	 * The step definitions below match with Katalon sample Gherkin steps
	 */
	String EdiFinalDeliveryDate = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyyyMMdd000000', 1, 0)
	String finalDeliveryDate = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('ddMMyy', 1, 0)
	String EDIdeliveryDateHour = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyyyMMddHHmm', 1, 0)
	String EdiOdpDate = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyyyMMdd000000', 0, 0)
	String timestamp = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyMMdd-HHmm', 0, 0)
	String odpRef = "Katalon_" + timestamp
	String MinEdiSpid = CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyMMdd=HHmmss00', 0, 0)
... (a lot more lines)

This code has a problem.

You should rather write:

import test.common.TimeHelper as TimeHelper
...
import org.junit.runner.RunWith

@RunWith(Cucumber.class)
@CucumberOptions(features="Include/features",glue="", plugin=["pretty", "html:ReportsCucumber","json:ReportsCucumber/cucumber.json"])

class MySCM {
	/**
	 * The step definitions below match with Katalon sample Gherkin steps
	 */
	String EdiFinalDeliveryDate = TimeHelper.getServerTimestamp('yyyyMMdd000000', 1, 0)
	String finalDeliveryDate = TimeHelper.getServerTimestamp('ddMMyy', 1, 0)
	String EDIdeliveryDateHour = TimeHelper.getServerTimestamp('yyyyMMddHHmm', 1, 0)
	String EdiOdpDate = TimeHelper.getServerTimestamp('yyyyMMdd000000', 0, 0)
	String timestamp = TimeHelper.getServerTimestamp('yyMMdd-HHmm', 0, 0)
	String odpRef = "Katalon_" + timestamp
	String MinEdiSpid = TimeHelper.getServerTimestamp('yyMMdd=HHmmss00', 0, 0)
...

The point is:

  1. The notation "CustomKeyword.'fully_qualified_class_name.method_name'.(args..)" works ONLY in Test Case scripts.
  2. If you write "CustomKeyword.'fully_qualified_class_name.method_name'.(args..)" in other locations (Keywords/package/your_class.groovy or in Includes/scripts/groovy/package/your_class.groovy), it will cause mysterious errors, such as “Caused by: java.lang.ClassFormatError: Illegal method name”
  3. Therefore, in any *.groovy codes under the Keywords and Includes folder, you should never write "CustomKeyword.xxxxxx"

@staniere

You wrote “CustomKeyword.xxxxxx” in a class under the Include/scripts/groovy folder. Why? — I guess, your read the following Katalon documentation page, and thought you should do so:

I think that this doc is not clear enough. It explains that you can write "CustomKeyword.xxxx" in Test Case script. But it does not explain how you should write a custom Groovy script under the Keywords and Include folder if you want to call another custom class.

The doc does not lie, but leaves you misunderstanding and confused.

@ThanhTo
@Shin

Any comment?

@staniere

Here I assume that you are a well-trained programmer and use the Script mode of Test Case editor in Katalon Studio; you rarely use Manual mode.

You can create a new test case "Test Cases/TC1" where you have a single line of Groovy script:

println CustomKeywords.'test.common.TimeHelper.getServerTimestamp'('yyyyMMdd000000', 1, 0)

You can write another test case "Test Cases/TC2" in the Script mode as the following:

import test.common.TimeHelper
println TimeHelper.getServerTimestamp('yyyyMMdd000000', 1, 0)

TC2 is also valid, it will work.

I want you to note:

  1. The "CustomKeyword.xxxxxx" notation was introduced for the Manual mode of Test Case editor. The Test Case editor is designed to show a dropdown list: and this GUI design is expressed as the format of "CustomKeyword.xxxxx" in the Script mode. This is the only reason why Katalon Studio employs that notation.
  2. If you do not use Manual mode GUI, you do not have to use "CustomKeyword.xxxxxx" notation in test cases at all.
  3. In *.groovy files under the Keywords folder, you would be tempted to write @Keyword annotation. The @Keyword annotation informs KS Manual mode so that the annotated class/method is to be included in the GUI dropdown list; this is the only reason why @Keyword annotation is there. Again, if you do not use the Manual mode, then you do not need the @Keyword annotation at all.