Rename screenshots taken on failure in PHPUnit Selenium - selenium

PHPUnit has an option to take a screenshot upon a Selenium test case failure. However, the screenshot filename generated is a hash of something - I don't know what exactly. While the test result report allows me to match a particular failed test case with a screenshot filename, this is troublesome to use.
If I could rename the screenshot to use the message from the failed assert as well as a timestamp for instance, it makes the screenshots much easier to cross-reference. Is there any way to rename the generated screenshot filename at all?

You could try something like this (it's works with selenium2):
protected function tearDown() {
$status = $this->getStatus();
if ($status == \PHPUnit_Runner_BaseTestRunner::STATUS_ERROR || $status == \PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE) {
$file_name = sys_get_temp_dir() . '/' . get_class($this) . ':' . $this->getName() . '_' . date('Y-m-d_H:i:s') . '.png';
file_put_contents($file_name, $this->currentScreenshot());
}
}
Also uncheck
protected $captureScreenshotOnFailure = FALSE;

I ended up using a modified version of #sectus' answer:
public function onNotSuccessfulTest(Exception $e) {
$file_name = '/' . date('Y-m-d_H-i-s') . ' ' . $this->getName() . '.png';
file_put_contents($this->screenshotPath . $file_name, base64_decode($this->captureEntirePageScreenshotToString()));
parent::onNotSuccessfulTest($e);
}
Although the conditional check in tearDown() works fine, based on Extending phpunit error message, I decided to go with onNotSuccessfulTest() as it seemed cleaner.
The filename could not accept colons :, or I would get an error message from file_get_contents: failed to open stream: Protocol error
The function currentScreenshot also did not exist, so I ended up taking the screenshot in a different way according to http://www.devinzuczek.com/2011/08/taking-a-screenshot-with-phpunit-and-selenium-rc/.

Another method I played around with, as I still wanted to use $this->screenshotUrl and $this->screenshotPath for convenient configuration:
I overwrote takeScreenshot from https://github.com/sebastianbergmann/phpunit-selenium/blob/master/PHPUnit/Extensions/SeleniumTestCase.php
protected function takeScreenshot() {
if (!empty($this->screenshotPath) &&
!empty($this->screenshotUrl)) {
$file_name = '/' . date('Y-m-d_H-i-s') . ' ' . $this->getName() . '.png';
file_put_contents($this->screenshotPath . $file_name, base64_decode($this->captureEntirePageScreenshotToString()));
return 'Screenshot: ' . $this->screenshotUrl . '/' . $file_name . ".png\n";
} else {
return '';
}
}

Related

yii2 saveAs two files, saves only one

i dont know why, but i have form where i specify two uploads (preview, detail) and when im trying to save them, detail is saved but preview not. Db has results as i expect - saved $slug in column imageSrc and imageDetailSrc
const UPLOAD_FILE_URL = 'uploads/recipes/';
const UPLOAD_FILE_DETAILS_URL = self::UPLOAD_FILE_URL.'details/';
$filePath = self::UPLOAD_FILE_URL . $slug . '.' . $this->imageSrc->extension;
$filePathDetail = self::UPLOAD_FILE_DETAILS_URL . $slug . '.' . $this->imageDetailSrc->extension;
if ($this->imageSrc->saveAs($filePath) && $this->imageDetailSrc->saveAs($filePathDetail)) {
$this->imageSrc = $slug . '.' . $this->imageSrc->extension;
$this->imageDetailSrc = $slug . '.' . $this->imageDetailSrc->extension;
}
if ($this->save(false, ['imageSrc', 'imageDetailSrc'])) {
return true;
}
Yii2 official documentation states that saveAs function uses move_uploaded_file() function to move the temporary file. Hence the temporary file gets deleted when you call saveAs function for the first time. If you do not want saveAs to delete then you should do send false as the second parameter to your saveAs function.
const UPLOAD_FILE_URL = 'uploads/recipes/';
const UPLOAD_FILE_DETAILS_URL = self::UPLOAD_FILE_URL.'details/';
$filePath = self::UPLOAD_FILE_URL . $slug . '.' . $this->imageSrc-
>extension;
$filePathDetail = self::UPLOAD_FILE_DETAILS_URL . $slug . '.' . $this->imageDetailSrc->extension;
if ($this->imageSrc->saveAs($filePath, false) && $this->imageDetailSrc->saveAs($filePathDetail)) {
$this->imageSrc = $slug . '.' . $this->imageSrc->extension;
$this->imageDetailSrc = $slug . '.' . $this->imageDetailSrc->extension;
}
if ($this->save(false, ['imageSrc', 'imageDetailSrc'])) {
return true;
}

PHP InstanceOf works locally but not on host server

I have an issue with PHP 7's instanceof statement that is only happening on certain conditions.
It seems that instanceof works locally on my dev machine (MAMP Pro running PHP 7.0.13) but not on my Hosted Server (HostEurope, PHP 7).
I have tried the following :
downgrading to PHP 5.6
using is_a instead
Using fully qualified name e.g. \Site\Ad
but they all exhibit the same behaviour.
I've tried Googling "PHP instanceof not working" and variations of it but I haven't found anything relevant.
I was wondering if anyone had experienced something similar or possible solutions to try?
The Code in question is:
<?php
namespace Site;
require_once(__DIR__."/../interface/IOutput.php");
require_once(__DIR__."/../lib/Lib.php");
require_once(__DIR__."/../site/AdMediumRectangle.php");
require_once(__DIR__."/../site/AdSnapBanner.php");
require_once(__DIR__."/../const/Const.php");
class AdFactory
{
/**
* Define(AD_BANNER, 0);
* Define(AD_RECTANGE, 1);
* Define(AD_SUPERBANNER, 2);
* Define(AD_SKYSCRAPER, 3);
**/
/**
* #param $object
* #return AdMediumRectangle|AdSnapBanner|string
*/
public static function CreateObject($object)
{
$ad = wire(pages)->get("/ads/")->children->getRandom();
if ($ad == null)
return new \Exception("No Random Ad found");
switch ($object) {
case AD_BANNER:
echo "AD_Banner Selected\r\n";
$adSnapBanner = new AdSnapBanner($ad);
return $adSnapBanner;
break;
case AD_RECTANGLE:
echo "AD Rectangle Created\r\n";
$adRectangle = new AdMediumRectangle($ad);
return $adRectangle;
break;
case AD_SUPERBANNER:
case AD_SKYSCRAPER:
default:
echo "AdFactory BlankObject created";
return "";
break;
}
}
public static function Markup($object)
{
$obj = AdFactory::CreateObject($object);
if (($obj instanceof AdSnapBanner) || ($obj instanceof AdMediumRectangle)) {
echo "InstanceOf worked";
return $obj->Markup();
}
else {
echo "return blankString";
return "";
}
}
}
Update : This is the code that calls the above AdFactory class
<?php
namespace Site;
require_once(__DIR__."/../interface/IOutput.php");
require_once(__DIR__."/../lib/Lib.php");
require_once(__DIR__."/../factory/AdFactory.php");
require_once (__DIR__."/../const/Const.php");
class AdInjector
{
public static function Inject($page, $ad_pos)
{
//Select an Ad from /Ads/ according to criteria
//$ads = wire(pages)->get("/ads/")->children;
$count = 1; //$ads->count();
if ($count > 0) {
$mod = $page->id % 3;
echo "mod=" . $mod . "\r\n";
if ($mod == $ad_pos) {
switch ($mod) {
case AD_POS_TITLE;
case AD_POS_BANNER:
//Pick an Snap Banner
echo "Banner Injected (banner):" . AD_BANNER . "\r\n";
return AdFactory::Markup(AD_BANNER);
break;
case AD_POS_SIBLINGS:
echo "Banner Injected (rect):" . AD_RECTANGLE . "\r\n";
//Pick an Ad Rectangle
return AdFactory::Markup(AD_RECTANGLE);
break;
default:
return "";
break;
}
} else
return "";
} else
return "";
}
}
instanceof is a language construct which is so essential to PHP that it is de facto impossible not to work properly.
The code you provided is not enough to tell where the issue might be happening.
Chances are, you have a folder not readable on your online server and simply get somewhere a null value instead of an expected object along your code. Ask yourself: "If it is not the object I expect, what else is it?"
Use var_dump() or printf() to investigate what your variables actually contain and you will find the error soon.
For your code, PHPUnit tests would be a benefit, or at least the use of assert() here and there in your code.
Turns out there was a bug in 1 of the API calls I was making to the Processwire CMS.
$ad = wire(pages)->get("/ads/")->children->getRandom();
And my local and server instance of Processwire was not the same version, which was news to me. I normally have it synchronised, including any modules I use.
I also suspect my null check is not correct PHP, to add to the problem.
It has to do with namespaces used in the code:
Locally (Code with no namespaces) I used this, working fine:
if ($xmlornot instanceof SimpleXMLElement) { }
But on the server (code with namespaces) only this worked:
if ($xmlornot instanceof \SimpleXMLElement) { }
See also this question/answer: instanceof operator returns false for true condition

Check HTTP status in cycle. Behat + Mink, Goutte driver

I try to check HTTP status in cycle:
foreach ($arrayOfLinks as $link) {
$this->getMainContext()->getSubcontext('mink')->visit($link);
$statusCode = $this->getSession()->getStatusCode();
if ($statusCode < 200 || $statusCode > 299) {
print 'Broken link ' . $href . ' status code is ' . $statusCode . "\n";
}
}
In the cycle it does not work consistently. It successfully checks about 20-40 links and then fails with error
The current node list is empty.
How can I fix it and what means this error?
I resolved problem. When I looking for all links on page and check status in the same foreach - I get error. When I split cycle into two cycles - it works

yii2 fixtures doesn't work properly

I have a problem with fixtures in yii2 , I just created all required file according to this document but it's not working.
let me explain , I have a module called Authyii and inside this module I have a model named User .
this is my directory structure :
my fixture file is like this :
namespace app\modules\Authyii\tests\fixtures;
use app\modules\Authyii\models;
use yii\test\ActiveFixture;
use yii\test\Fixture;
class UserFixture extends ActiveFixture
{
public $modelClass = 'app\modules\Aythyii\models\User';
public $tableName = 'authyii_user';
}
this is my command line :
but after I type 'yes' and command line says :
but when I check my database there is not new record inside authyii_user tables .
what I missed ?
File User.php id data dir must have table name authyii_user.php. In framework source code in file ActiveFixture.php line with code:
$dataFile = dirname($class->getFileName()) . '/data/'
. $this->getTableSchema()->fullName . '.php';
Best regards.
There is method getFixturesConfig() in \vendor\yiisoft\yii2\console\controllers\FixtureController.php
private function getFixturesConfig($fixtures)
{
$config = [];
foreach ($fixtures as $fixture) {
$isNamespaced = (strpos($fixture, '\\') !== false);
$fullClassName = $isNamespaced ? $fixture . 'Fixture' : $this->namespace . '\\' . $fixture . 'Fixture';
if (class_exists($fullClassName)) { // <<< I think you lose your UserFixture here
$config[] = $fullClassName;
}
}
return $config;
}
You should check what $fullClassName Yii expects it to be (for example logging or echoing it) and tweak your UserFixture's namespace accordingly.

Can anyone help me with this error

if (isset($_POST['Software'])) {
$_POST['Software']['sw_icon'] = $model->sw_icon;
$model->attributes = $_POST['Software'];
$uploadedFile = CUploadedFile::getInstance($model, 'sw_icon');
$model->attributes = $_POST['Software'];
$model->updated_date = date("Y-m-d H:i");
if ($model->save()) {
if (!empty($uploadedFile)) { // check if uploaded file is set or not
$uploadedFile->saveAs(Yii::app()->basePath . '/../images/software_icons/' . $model->sw_icon);
}
Yii::app()->user->setFlash('success', 'Software updated successfully.');
$this->redirect(array('index'));
}
}
When I use the above code i get the following error
...move_uploaded_file(): The second argument to copy() function
cannot be a directory.
Can you show me the result of Yii::app()->basePath . '/../images/software_icons/' . $model->sw_icon,seems like it a directory
You can move a file to another file name. You can't move a file to a folder.
Try replace Yii::app()->basePath . '/../images/software_icons/' . $model->sw_icon on
this: Yii::app()->basePath . '/../images/software_icons/newfile'