При попытке проверить некоторые параметры mvn/runner по сравнению с одним вариантом сценария я столкнулся с проблемой с параметром чтения.
Эта работа заключается в том, чтобы позволить тестировщикам определять dataRow (информацию об учетной записи пользователя) во время выполнения и использовать уникальную аутентификацию, специфичную для текущего файла функций. Если тест вызывается из команды runner или mvn, мы не хотим, чтобы каждый файл функций аутентифицировался с одним и тем же пользователем, а используем аутентификацию, вызываемую в процессе инициализации конфигурации.
ПРИМЕЧАНИЕ. В конфигурации есть аналогичный код для выполнения вызовов аутентификации только при наличии dsRow, а затем сохранения этого результата аутентификации в файле для повторного использования всеми функциями, определенными в команде runner или mvn. Эта часть конфигурации работает, как и ожидалось
Вот текущий фон, который в настоящее время работает, как и ожидалось, для строки, определенной пользователем, при локальном запуске файла функций.
Background: Authentication PreRequisites
* def dataSourceRow = karate.get('karate.dsRow', 1)
* def dataSourceEnv = karate.get('karate.env', 'dev')
* callonce read('../../../../service-config.js') { dsRow: '#(dataSourceRow)' , env: '#(dataSourceEnv)' }
* if (skipDomainFlag) {karate.logger.debug('skipDomainFlag is set to true so Domain calls cannot be ran!'); karate.abort(); }
* callonce read('classpath:adapters/domainsession.feature')
* configure afterFeature = function(){ karate.call('classpath:adapters/logout.feature'); }
* url baseUrlDomain + domainPath
* configure headers = domainHeaders
* header host = domainHost
При попытке проверить, был ли передан karate.dsRow
в операторе if, последующий вызов чтения не работает, как в одной строке.
Вот варианты, которые я пробовал: Я получил следующее для работы, но для этого требуется, чтобы вызов (один раз) находился в отдельной строке, и это не разрешено в последующем операторе if. Это работает при локальном запуске файла функций, но не работает при запуске через опцию mvn/runner.
* if (!(karate.properties['karate.dsRow'])) domainAuth = read('classpath:adapters/domainsession.feature')
* callonce domainAuth
...
org.graalvm.polyglot.PolyglotException: ReferenceError: "domainAuth" is not defined
Установка параметра callonce после оценки dsRow приводит к следующему:
* if (!(karate.properties['karate.dsRow'])) domainAuth = read('classpath:adapters/domainsession.feature')
* if (!(karate.properties['karate.dsRow'])) karate.callonce('#(domainAuth)')
...
01: if (!(karate.properties['karate.dsRow'])) karate.callonce('#(domainAuth)')
<<<<
org.graalvm.polyglot.PolyglotException: js failed:
>>>>
01: read('#(domainAuth)
<<<<
org.graalvm.polyglot.PolyglotException: SyntaxError: Unnamed:1:19 Missing close quote
read('#(domainAuth)
^
or
* if (!(karate.properties['karate.dsRow'])) domainAuth = read('classpath:adapters/domainsession.feature')
* if (!(karate.properties['karate.dsRow'])) karate.callonce(domainAuth)
...
01: if (!(karate.properties['karate.dsRow'])) karate.callonce(domainAuth)
<<<<
org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (callonce) on com.intuit.karate.core.ScenarioBridge@4af5dcab failed due to: no applicable overload found (overloads: [Method[public java.lang.Object com.intuit.karate.core.ScenarioBridge.callonce(java.lang.String)], Method[public java.lang.Object com.intuit.karate.core.ScenarioBridge.callonce(boolean,java.lang.String)]], arguments: [JavaObject[classpath:adapters/domainsession.feature (com.intuit.karate.core.FeatureCall)] (HostObject)])
Объединение вызовов в одну строку приводит к той же перегруженной ошибке.
01: if (!(karate.properties['karate.dsRow'])) { domainAuth = read('classpath:adapters/domainsession.feature'); karate.callonce(domainAuth) }
<<<<
org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (callonce) on com.intuit.karate.core.ScenarioBridge@3ea98e66 failed due to: no applicable overload found (overloads: [Method[public java.lang.Object com.intuit.karate.core.ScenarioBridge.callonce(java.lang.String)], Method[public java.lang.Object com.intuit.karate.core.ScenarioBridge.callonce(boolean,java.lang.String)]], arguments: [JavaObject[classpath:adapters/domainsession.feature (com.intuit.karate.core.FeatureCall)] (HostObject)])
or
* if (!(karate.properties['karate.dsRow'])) { karate.set('domainAuth', karate.read('classpath:adapters/domainsession.feature')); karate.callonce('#(domainAuth)'); }
...
01: if (!(karate.properties['karate.dsRow'])) { karate.set('domainAuth', karate.read('classpath:adapters/domainsession.feature')); karate.callonce('#(domainAuth)'); }
<<<<
org.graalvm.polyglot.PolyglotException: js failed:
>>>>
01: read('#(domainAuth)
<<<<
org.graalvm.polyglot.PolyglotException: SyntaxError: Unnamed:1:19 Missing close quote
read('#(domainAuth)
^
Было бы здорово, если бы опция call(once) read работала в правой части оценки if, аналогично опции с одной строкой, чтобы приспособиться к таким ситуациям. Если это нежелательный подход, какие еще варианты вы видите, которые я мог пропустить?
ОБНОВЛЕНИЕ: пример кода для локального тестирования testUrl.feature
Feature:
Scenario:
* def testUrl = 'http://www.google.com'
тест.функция
Feature: Test for test call and callonce after a conditional
Background: Authentication PreRequisites
* def testUrl = karate.get('karate.testUrl', 'http://www.bing.com')
#**** Calls combined for troubleshooting of the call/callonce function after a conditional
#***** uncomment only 1 of the below statements
# * if (!(karate.properties['karate.testUrl'])) { karate.set('testUrlFile', karate.read('testUrl.feature')); karate.call('#(testUrlFile)'); }
# * if (!(karate.properties['karate.testUrl'])) { karate.set('testUrlFile', karate.read('testUrl.feature')); karate.call(testUrlFile); }
# * if (!(karate.properties['karate.testUrl'])) { karate.set('testUrlFile', karate.read('testUrl.feature')); karate.callonce('#(testUrlFile)'); }
# * if (!(karate.properties['karate.testUrl'])) { karate.set('testUrlFile', karate.read('testUrl.feature')); karate.callonce(testUrlFile); }
#**** Calls separated for troubleshooting of the call/callonce function after a conditional
# * if (!(karate.properties['karate.testUrl'])) { karate.set('testUrlFile', karate.read('testUrl.feature')) }
# * if (!(karate.properties['karate.testUrl'])) { karate.log('testUrlFile is ',testUrlFile) }
#***** uncomment only 1 of the below statements to accompany the above 2 lines
# * if (testUrlFile) { karate.call('#(testUrlFile)'); }
# * if (testUrlFile) { karate.call(testUrlFile); }
# * if (testUrlFile) { karate.callonce('#(testUrlFile)'); }
# * if (testUrlFile) { karate.callonce(testUrlFile); }
* url testUrl
Scenario:
Given path '/'
When method GET
Then status 200
я буду работать над примером, но это может занять некоторое время, чтобы создать что-то, чем можно поделиться. Что касается опечатки, то я ее не вижу
Что касается This works in the run of the feature file locally, but fails when running thru mvn/runner option.
, это правильно, потому что оператор вызова необходим при локальном запуске для вызова аутентификации. Попытка исключить функцию вызова, как и предыдущую функцию чтения, приводит к ошибкам, показанным в последующих строках.
возможно, это не опечатка, но я не могу следить за большим потоком, который вы предоставили. возможно, в переменной domainAuth
нет одинарной кавычки, как говорится в последней строке сообщения об ошибке. для меня это тот случай, когда нужен пример, который я могу запустить локально
позвольте мне предположить - пожалуйста, не делайте этого: karate.callonce('#(domainAuth)')
и сделайте это вместо этого: karate.callonce(domainAuth)
- см.: github.com/karatelabs/karate#rules-for-embedded-expressions
это было предпринято, как указано выше * if (!(karate.properties['karate.dsRow'])) karate.callonce(domainAuth)
во второй части «Установка параметра callonce после оценки dsRow приводит к следующим» результатам блока кода
@PeterThomas. Из добавленного выше примера видно, что функции call и callonce не работают после условных операторов. Пожалуйста, попробуйте и проверьте, прав ли я в этой ошибке, или я делаю что-то не так. Я просто устанавливаю для проверки systemproperty значение false, чтобы вызвать условия без необходимости совершать вызовы через исполнителя команды mvn.
меня устраивает. Я не могу запустить ваш пример, поэтому не могу сказать. возможно, callonce не предназначен для работы с условными операторами, и я не помню, чтобы какая-либо команда делала это или сообщала об этом
it works for me
- как это работает в ваших настройках - не могли бы вы поделиться? Не знаете, почему вы не можете запустить приведенный выше пример, поскольку это 2 простых файла функций, в которых вы раскомментируете различные строки в примере, а затем можете увидеть ошибки как для операторов callonce, так и для операторов вызова за условным оператором? Вы используете 1.3.1 с java 8 (извините, это не было указано в посте) или другую версию?
добавил ответ с моим примером.
У меня работает, вот простой пример:
Feature:
Background:
* if (true) karate.callonce('called.feature')
Scenario: first
* print 'first'
Scenario: second
* print 'second'
Выход:
23:52:18.580 [main] INFO com.intuit.karate - >> lock acquired, begin callonce: read('called.feature')
23:52:18.586 [main] INFO com.intuit.karate - [print] in called
23:52:18.598 [main] INFO com.intuit.karate - << lock released, cached callonce: read('called.feature')
23:52:18.602 [main] INFO com.intuit.karate - [print] first
23:52:18.606 [main] INFO com.intuit.karate - [print] second
Таким образом, когда-то кажется, что вызов работает, если в файл передается действительная строка, но передача переменных не работает, отсюда и моя проблема. Я жестко запрограммировал файл функций в функцию callonce, ` * if (!(karate.properties['karate.testUrl'])) { karate.callonce('testUrl.feature'); }, but this requires all variables set in the called function to not be available as they are within a different scope or have to be assigned to a variable, differently than simply being usable after a
* callonce read('classpath:testUrl.feature')` использование. Таким образом, комбинация read и callonce терпит неудачу.
Изучив код в ScenarioBridge.java, я обнаружил, что вместо чтения файла я могу просто добавить логическое значение для sharedScope в метод callonce, и это, похоже, решило проблему на данный момент...` * if (!( karate.properties['karate.testUrl'])) { karate.callonce(true, 'testUrl.feature'); }`
Хотя ваше решение работает, оно не решило мою проблему. Мне пришлось просмотреть код, чтобы найти обходной путь, поскольку область действия callonce без функции чтения не является общей областью действия, и в этом была вся проблема.
@mike Я бы никогда не догадался, что вопрос был связан с общей областью действия, но ладно
Вопрос был связан с использованием чтения (что делает вызов общей областью) и вызова/вызова после оценки, как указано в заголовке и показано в примере. Извините, что sharedScope не был упомянут, но я нашел это как проблему только при поиске исходного кода карате.
Посмотрев исходный код, в частности ScenarioBridge.java, я обнаружил, что вместо использования метода параллельного чтения, чтобы включить файл в общую область, я могу просто добавить логическое значение для sharedScope в метод callonce, и это, похоже, решило проблема на данный момент...
Текущее рабочее решение
* if (!(karate.properties['karate.testUrl'])) { karate.callonce(true, 'testUrl.feature'); }
karate.callonce()
действительно «недокументирован», потому что мы чувствовали, что это будет стимулировать сложные в обслуживании тесты (как я подозреваю, здесь дело обстоит именно так). Я не рекомендую это, потому что мы на самом деле надеялись удалить его в будущем.
This works in the run of the feature file locally, but fails when running thru mvn/runner option.
- этого быть не должно, поэтому я настаиваю на способе повторения. Я также чувствую, что это слишком сложно, и другим будет очень сложно поддерживать его в долгосрочной перспективе. у вас тоже опечатка здесь:read('#(domainAuth)')