<?php /** * Copyright 2015 - 2016 Xenofon Spafaridis * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ use Phramework\Testphase\Globals; \Phramework\Testphase\Testphase::setBase('http://jsonplaceholder.typicode.com/'); Globals::set('getIds', [7, 6]); //$testParser = new \Phramework\Testphase\TestParser('./tests/tests/GETById-iterator.json'); //$testParser->createTest(); //die();
/** * Invoke scripts * @return integer Returns indicate how the script exited. * Normal exit is generally represented by a 0 return. */ public function invoke() { $arguments = $this->arguments; if (($serverHost = $arguments->{'server-host'}) !== null) { $this->server = new Server($serverHost, $arguments->{'server-root'}); $this->server->start(); } //Include bootstrap file if set if ($bootstrapFile = $arguments->bootstrap) { require $bootstrapFile; } echo 'testphase v' . Testphase::getVersion() . PHP_EOL; if ($arguments->help) { echo 'Help:' . PHP_EOL; $printer = new ConsoleOptionPrinter(); echo $printer->render(static::getArgumentSpecifications()); return 0; } elseif ($arguments->debug) { echo 'Enabled options: ' . PHP_EOL; foreach ($arguments as $key => $spec) { echo $spec; } } try { $testParserCollection = $this->getTestParserCollection(); } catch (\Exception $e) { echo $e->getMessage(); return $this->stop(1); } //Statistics object $stats = (object) ['tests' => count($testParserCollection), 'success' => 0, 'error' => 0, 'failure' => 0, 'ignore' => 0, 'incomplete' => 0, 'errors' => []]; $testIndex = 0; foreach ($testParserCollection as $test) { //Check if subdir argument is set if (isset($arguments->subdir) && $arguments->subdir !== null) { //If so check if file name passes the given pattern //Remove base dir from filename $cleanFilename = trim(str_replace($arguments->dir, '', $test->getFilename()), '/'); $match = false; //Check if file name matches any of the subdir patterns foreach ($arguments->subdir as $pattern) { $pattern = '@' . $pattern . '@'; if (!!preg_match($pattern, $cleanFilename)) { $match = $match || true; break; } } if (!$match) { //Ignore $stats->ignore += 1; if ($arguments->verbose) { echo sprintf('I %s', $test->getFilename()) . PHP_EOL; } else { echo 'I'; } continue; } } $meta = $test->getMeta(); if (isset($meta->ignore) && $meta->ignore) { if ($arguments->verbose) { echo sprintf('I %s', $test->getFilename()) . PHP_EOL; } else { echo 'I'; } $stats->ignore += 1; continue; } if (isset($meta->incomplete) && $meta->incomplete !== false) { $stats->incomplete += 1; } try { //Complete test's testphase collection $test->createTest(); } catch (\Exception $e) { echo sprintf('Unable to create test from file "%s" %s With message: "%s"', $test->getFilename(), PHP_EOL, $e->getMessage()) . PHP_EOL; return $this->stop(1); } $testphaseCollection = $test->getTest(); //Include number of additional testphase collections $stats->tests += count($testphaseCollection) - 1; //Iterate though test parser's testphase collection foreach ($testphaseCollection as $testphase) { try { $testphase->run(function ($responseStatusCode, $responseHeaders, $responseBody, $responseBodyObject = null) use($test, $arguments) { //todo move to TestParser $export = $test->getExport(); //Fetch all test exports and add them as globals foreach ($export as $key => $value) { $path = explode('.', $value); $pathValue = $responseBodyObject; foreach ($path as $p) { //@todo implement array index $arrayIndex = 0; if (is_array($pathValue)) { $pathValue = $pathValue[$arrayIndex]->{$p}; } else { $pathValue = $pathValue->{$p}; } } Globals::set($key, $pathValue); } if ($arguments->debug) { echo 'Response Status Code:' . PHP_EOL; echo $responseStatusCode . PHP_EOL; echo 'Response Headers:' . PHP_EOL; print_r($responseHeaders); echo PHP_EOL; echo 'Response Body:' . PHP_EOL; echo json_encode($responseBodyObject, JSON_PRETTY_PRINT) . PHP_EOL; } }); //Echo successful char if ($arguments->verbose) { echo sprintf('. %s', $test->getFilename()) . PHP_EOL; } else { echo '.'; } $stats->success += 1; } catch (UnsetGlobalException $e) { //Error message $message = $e->getMessage(); $message = sprintf(self::colored('Test "%s" failed with message', 'red') . PHP_EOL . ' %s' . PHP_EOL, $test->getFilename(), $message); //push message to error message $stats->errors[] = $message; //Echo unsuccessful char if ($arguments->verbose) { echo sprintf('F %s', $test->getFilename()) . PHP_EOL; } else { echo 'F'; } //print if immediate if ($arguments->immediate) { echo PHP_EOL . $message . PHP_EOL; } //Error message $stats->error += 1; } catch (\Exception $e) { //Error message $message = $e->getMessage(); if ($arguments->debug) { $message .= PHP_EOL . $testphase->getResponseBody(); } $message = sprintf(self::colored('Test "%s" failed with message', 'red') . PHP_EOL . ' %s' . PHP_EOL, $test->getFilename(), $message); if (get_class($e) == IncorrectParametersException::class) { $message .= 'Incorrect:' . PHP_EOL . json_encode($e->getParameters(), JSON_PRETTY_PRINT) . PHP_EOL; } elseif (get_class($e) == MissingParametersException::class) { $message .= 'Missing:' . PHP_EOL . json_encode($e->getParameters(), JSON_PRETTY_PRINT) . PHP_EOL; } //push message to error message $stats->errors[] = $message; //Echo unsuccessful char if ($arguments->verbose) { echo sprintf('F %s', $test->getFilename()) . PHP_EOL; } else { echo 'F'; } //print if immediate if ($arguments->immediate) { echo PHP_EOL . $message . PHP_EOL; } $stats->failure += 1; } ++$testIndex; //Show only 80 characters per line if (!($testIndex % 79)) { echo PHP_EOL; } } } echo PHP_EOL; if ($arguments->{'show-globals'}) { echo 'Globals:' . PHP_EOL; echo Globals::toString() . PHP_EOL; } //don't print if immediate is true if (!$arguments->immediate && !empty($stats->errors)) { echo 'Errors:' . PHP_EOL; foreach ($stats->errors as $e) { echo $e . PHP_EOL; } } echo 'Complete!' . PHP_EOL; echo 'Tests:' . $stats->tests . ', '; Binary::output('Successful: ' . $stats->success, 'green'); echo ', '; Binary::output('Ignored: ' . $stats->ignore, 'yellow'); echo ', '; Binary::output('Incomplete: ' . $stats->incomplete, 'yellow'); echo ', '; Binary::output('Error: ' . $stats->error, 'red'); echo ', '; Binary::output('Failure: ' . $stats->failure . PHP_EOL, 'red'); echo 'Memory usage: ' . (int) (memory_get_usage(true) / 1048576) . ' MB' . PHP_EOL; echo 'Elapsed time: ' . (time() - $_SERVER['REQUEST_TIME']) . ' s' . PHP_EOL; if ($stats->error > 0) { return $this->stop(1); } if ($stats->failure > 0) { return $this->stop(2); } return $this->stop(0); }
/** * @todo clean up */ public function createTest() { $testphaseCollection = []; if (!empty((array) $this->contentsParsed->request->iterators)) { //searchAndReplace in request->iterators first $iterators = $this->searchAndReplace($this->contentsParsed->request->iterators); //replace back to contentsParsed $this->contentsParsed->request->iterators = $iterators; //Get combinations of iterator values $combinations = Util::cartesian((array) $iterators); } else { //Add a single test with no combinations $combinations = [[]]; } foreach ($combinations as $combination) { //Set combination foreach ($combination as $combinationKey => $combinationValue) { Globals::set($combinationKey, $combinationValue); } //Recursive search whole object $contentsParsed = $this->searchAndReplace($this->contentsParsed); $requestBody = null; $requestBodies = []; if (isset($contentsParsed->request->body) && !empty($contentsParsed->request->body)) { if (!is_array($contentsParsed->request->body)) { //Work with array $contentsParsed->request->body = [$contentsParsed->request->body]; } foreach ($contentsParsed->request->body as $body) { //Push to bodies $requestBodies[] = is_object($body) ? json_encode($body) : $body; } } //In case there is no request body, then at least one test must be created if (empty($requestBodies)) { $requestBodies[] = null; } foreach ($requestBodies as $requestBody) { //Create a Testphase object using parsed rule $testphase = (new Testphase($contentsParsed->request->url, $contentsParsed->request->method, $contentsParsed->request->headers, $requestBody))->expectStatusCode($contentsParsed->response->statusCode)->expectResponseHeader($contentsParsed->response->headers); $testphase->expectJSON(isset($contentsParsed->meta->JSONbody) ? $contentsParsed->meta->JSONbody : true); //Add rule objects to validate body foreach ($contentsParsed->response->ruleObjects as $key => $ruleObject) { if (is_string($ruleObject)) { $testphase->expectObject(ObjectValidator::createFromJSON($ruleObject)); } elseif (is_subclass_of($ruleObject, \Phramework\Validate\BaseValidator::class)) { $testphase->expectObject($ruleObject); } else { $testphase->expectObject(ObjectValidator::createFromObject($ruleObject)); } } //push test $testphaseCollection[] = $testphase; //todo set only once $this->export = $contentsParsed->response->export; } } $this->testphaseCollection = $testphaseCollection; }