Интерактивная консоль при запуске юнит-тестов в Codeception

Вопрос или проблема

Интерактивная консоль при запуске юнит-тестов в Codeception

У нас есть 2 сценария:

  1. Привязка аккаунта (регистрация номера банковского счета к сервису)
  2. Подтверждение OTP (ввод кода OTP, отправленного на мобильный телефон клиента)

Некоторые ответы от привязки аккаунта использовались во втором сценарии, но мне нужно “вставить” значение кода OTP перед вторым шагом.

Что я сделал до сих пор в Codeception — использовал Codeception\Lib\Actor\Shared\Pause:

    public function testVerificationFlow()
    {
        $faker = Faker\Factory::create();
        
        $sequence="0000";
        $partnerReferenceNo = $faker->numerify('###########') . $sequence;
        $bankAccountNo      = $faker->numerify('##########');
        $bankCardNo         = $faker->randomNumber(4, true);
        $limit              = 250000.00;
        $email              = $faker->email();
        $custIdMerchant     = $faker->numerify('##########');
        
        $response = $this->autopay->accountBinding(
            $partnerReferenceNo,
            $bankAccountNo,
            $bankCardNo,
            $limit,
            $email,
            $custIdMerchant
        );

        codecept_debug($response);
        $this->assertEquals($response->responseCode, self::RESP_CODE_ACCOUNT_BINDING);
        
        $otpCode="";
        
        // как вставить значение $otpCode здесь?
        $this->pause();

        codecept_debug($otpCode);

        $verifyOtpResponse = $this->autopay->verifyOtp(
            $partnerReferenceNo,
            $response->originalReferenceNo,
            $response->chargeToken,
            $otpCode,
        );

        codecept_debug($verifyOtpResponse);
        $this->assertEquals($verifyOtpResponse->responseCode, self::RESP_CODE_OTP_VERIFY);

    }

Проект Hoa\Console заброшен уже много лет назад

 Выполнение ПРИОСТАНОВЛЕНО, начинается интерактивная оболочка...
  Введите команды, чтобы попробовать их:
  - ENTER для продолжения
  - TAB для автозаполнения
  - F5 для сохранения команды
  - F6 для переключения автосохранения успешных команд
  - F8 для просмотра сохраненных команд
  - F10 для очистки сохраненных команд

Я все еще не знаю, что использовать, когда приостановлен модульный тест. Любые идеи / ключевые слова для поиска в Google будут признательны.

Я только что понял, что Hoa\Console использует readline() для “приостановки” процесса.

$otpCode = readline('Пожалуйста, введите OTP перед запуском testVerifyOtp: ');

$verifyOtpResponse = $this->autopay->verifyOtp(
    $partnerReferenceNo,
    $response->referenceNo,
    $response->additionalInfo->chargeToken,
    (string) $otpCode,
);

codecept_debug($verifyOtpResponse);
$this->assertEquals($verifyOtpResponse->responseCode, self::RESP_CODE_OTP_VERIFY);
Пожалуйста, введите OTP перед запуском testVerifyOtp: 364612
✔ AutopayTest: Проверка потока (9.85с)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Время: 00:09.862, Память: 10.00 МБ

OK (1 тест, 2 утверждения)

Это будет мое решение в чистой программе.

class OTP_Verify_Response {
    
    protected $data_file = false;
    protected $questions = array();
    protected $responses = array();
    
    public function __construct($data_file) {
        if (!empty($data_file) and file_exists($data_file)) {
            $this->data_file = realpath($data_file);
        }
        if (!empty($this->data_file)) {
            $data = file_get_contents($this->data_file);
            $data = json_decode($data, true);
        } else {
            $data = array();
        }
        $this->questions = $data['questions'];
        $this->responses = $data['responses'];
    }
    
    public function doQuestions() {
        if ($question_answer = $this->_askQuestion("Пожалуйста, введите OTP перед запуском testVerifyOtp:", "testVerifyOtp")) {
            $this->_testVerifyOtp($question_answer); // Это было отвечено
        } else {
            return false; // Нам нужен ответ
        }
        // Зададим другой вопрос ...
        return $this->closeDataFile();
    }
    
    protected function _testVerifyOtp($question_answer) {
        // делаем что-то с $question_answer
    }
    
    protected function _askQuestion($question_text, $question_field) {
        if (empty($question_text)) {
            return false;
        }
        if (!empty($_POST) and array_key_exists($question_field, $_POST)) {
            $question_answer = $_POST[$question_field];
            $this->_storeAnswer($question_text, $posted_answer);
        } elseif ($question_text and !empty($question_text)) {
            $question_answer = $this->_answerQuestion($question_text);
        } else {
            $question_answer = false;
        }
        if (!empty($question_answer)) {
            return $question_answer;
        }
        echo "<div>{$question_text}? <input name="{$question_field}" value="{$_POST[$question_field]}" /></div>";
        return false;
    }
    
    protected function _answerQuestion($question_text) {
        $question_hash = $this->_createQuestionHash($question_text);
        if ($this->responses[$question_hash]) {
            return $this->responses[$question_hash];
        }
        return false;
    }
    
    protected function _storeAnswer($question_text, $posted_answer) {
        $question_hash = $this->_createQuestionHash($question_text);
        $this->questions[$question_hash] = $question_text;
        $this->responses[$question_hash] = $posted_answer;
        return $posted_answer;
    }
    
    protected function _createQuestionHash($question_text) {
        $question_hash = md5($question_text);
        return $question_hash;
    }
    
    public function update_store_data() {
        $store_data = array();
        $store_data['questions'] = $this->questions;
        $store_data['responses'] = $this->responses;
        if (!empty($this->data_file)) {
            return file_put_contents($this->data_file, json_encode($store_data));
        }
        return false;
    }
    
    public function closeDataFile() {
        if (!empty($this->data_file) and file_exists($this->data_file)) {
            return unlink($this->data_file);
        }
        return false;
    }
    
}

Идея состоит в том, чтобы использовать POST, а также файл ДАННЫХ и сохранить каждый вопрос / ответ

$verify_item = new OTP_Verify_Response("/tempFile.tmp");
$verify_item->doQuestions();

(Вам нужно будет обернуть это в <form></form>), но в идеале это будет работать.

Ответ или решение

Для решения задачи по внедрению значения кода OTP в процессе запуска модульного теста с использованием Codeception, вы сделали правильные шаги в направлении использования метода readline() для паузы выполнения теста и получения пользовательского ввода. Давайте подытожим ключевые моменты и предложим полное решение.

Полное Решение

  1. Импорт необходимых библиотек: Убедитесь, что вы используете все необходимые библиотеки. В данном случае вам может понадобиться Faker для генерации случайных данных, а также класс readline для ввода данных.

  2. Основной код теста: Мы добавим вызов readline() для получения кода OTP от пользователя, а также условия для проверки корректности этого кода и продолжения теста.

Ниже представлена переработанная версия вашего метода testVerificationFlow с учетом предложенных изменений:

public function testVerificationFlow()
{
    $faker = Faker\Factory::create();

    $sequence = "0000";
    $partnerReferenceNo = $faker->numerify('###########') . $sequence;
    $bankAccountNo = $faker->numerify('##########');
    $bankCardNo = $faker->randomNumber(4, true);
    $limit = 250000.00;
    $email = $faker->email();
    $custIdMerchant = $faker->numerify('##########');

    // Вызов метода для привязки счета
    $response = $this->autopay->accountBinding(
        $partnerReferenceNo,
        $bankAccountNo,
        $bankCardNo,
        $limit,
        $email,
        $custIdMerchant
    );

    codecept_debug($response);
    $this->assertEquals($response->responseCode, self::RESP_CODE_ACCOUNT_BINDING);

    // Получение кода OTP от пользователя
    $otpCode = readline('Пожалуйста, введите код OTP перед выполнением testVerifyOtp: ');

    codecept_debug($otpCode);

    // Проверка кода OTP
    $verifyOtpResponse = $this->autopay->verifyOtp(
        $partnerReferenceNo,
        $response->originalReferenceNo,
        $response->chargeToken,
        (string)$otpCode
    );

    codecept_debug($verifyOtpResponse);
    $this->assertEquals($verifyOtpResponse->responseCode, self::RESP_CODE_OTP_VERIFY);
}

Пояснение

  • Мы заменили линию с pause() на readline(), чтобы получить прямой ввод пользователя, который будет использоваться в следующем шаге теста.

  • Ввод пользователя будет сохранен в переменную $otpCode, которая затем будет использована при вызове метода для проверки OTP.

  • Это позволяет вам взаимодействовать с тестом в интерактивном режиме, что упрощает процесс введения данных.

Заключение

Использование readline() обеспечивает более эффективное и интуитивно понятное взаимодействие во время теста, позволяя вам вводить необходимые значения в реальном времени. Это решение полностью охватывает вашу задачу по внедрению значения кода OTP и должно сработать корректно в контексте вашего теста с Codeception.

Оцените материал
Добавить комментарий

Капча загружается...