I am trying to write some tests for my Silex app and have run into an issue.
I have the following phpunit.xml file
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="./bootstrap.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
>
<testsuites>
<testsuite name="Management Test Suite">
<directory>./</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>../src/</directory>
</whitelist>
</filter>
</phpunit>
The bootstrap code is
<?php
use Symfony\Component\HttpKernel\Client;
function getJSONResponse($app, Client $client, $url, $params = array())
{
$params['test_key'] = $app['test_key'];
$client->request('GET', $url, $params);
$response = $client->getResponse();
$data = json_decode($response->getContent(), true);
return $data;
}
My first test file is as follows
<?php
require_once $_SERVER['frog_docroot'] . '/www/vendor/autoload.php';
class DefaultTest extends Silex\WebTestCase
{
public function createApplication()
{
return require $_SERVER['frog_docroot'] . '/www/src/app.php';
}
public function testInvalidUrlThrowsException()
{
$client = $this->createClient();
$data = getJSONResponse($this->app, $client, '/some/url/that/does/not/exist');
$this->assertContains('No route found for "GET /some/url/that/does/not/exist"', $data['message']);
}
}
And my second one is
<?php
require_once $_SERVER['frog_docroot'] . '/www/vendor/autoload.php';
class AnotherTest extends Silex\WebTestCase
{
public function createApplication()
{
return require $_SERVER['frog_docroot'] . '/www/src/app.php';
}
public function testSearchReturnsResults()
{
$client = $this->createClient();
$data = getJSONResponse($this->app, $client, '/packages/search', array(
'search' => 'something',
'offset' => 0,
'limit' => 10,
));
$this->assertSame(array(
'data' => array(
'1' => 'Some Package',
),
'offset' => 0,
'limit' => 10,
), $data);
}
}
The issue is that if I run the test individually they both pass.
If I run them as part of the test suite an exception is thrown
There was 1 failure:
1) AnotherTest::testSearchReturnsResults
Failed asserting that Array (
'message' => 'No route found for "GET /packages/search"'
'code' => 0
) is identical to Array (
'data' => Array (
'1' => 'Some Package'
)
'offset' => 0
'limit' => 10
'more' => false
).
Is there anything obviously wrong with how I am trying to write the tests?
Cheers
I ran into the same issue. All I had to do (although I didn't like that solution) was to use require and include instead of require_once and include_once
Related
I have a cakephp 3.7 plugin as its own stand-alone project. But am encountering the failures below when running unit tests. It seems after moving this outside of a parent project, the fixtures are no longer being built. Not sure how to instruct cake to build them.
Cake\Database\Exception: Cannot describe teams. It has 0 columns.
Here is my tests/bootstrap file. These tests were previously working until I decided to move this plugin out of the parent project.
<?php
$findRoot = function ($root) {
do {
$lastRoot = $root;
$root = dirname($root);
if (is_dir($root . '/vendor/cakephp/cakephp')) {
return $root;
}
} while ($root !== $lastRoot);
throw new Exception("Cannot find the root of the application, unable to run tests");
};
$root = $findRoot(__FILE__);
unset($findRoot);
chdir($root);
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
define('ROOT', $root);
define('APP_DIR', 'App');
define('WEBROOT_DIR', 'webroot');
define('APP', ROOT . '/tests/');
define('CONFIG', ROOT . '/tests/config/');
define('WWW_ROOT', ROOT . DS . WEBROOT_DIR . DS);
define('TESTS', ROOT . DS . 'tests' . DS);
define('TMP', ROOT . DS . 'tmp' . DS);
define('LOGS', TMP . 'logs' . DS);
define('CACHE', TMP . 'cache' . DS);
define('CAKE_CORE_INCLUDE_PATH', ROOT . '/vendor/cakephp/cakephp');
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
define('CAKE', CORE_PATH . 'src' . DS);
require_once ROOT . '/vendor/cakephp/cakephp/src/basics.php';
require ROOT . '/vendor/autoload.php';
use Cake\Core\Configure;
use Cake\Core\Configure\Engine\PhpConfig;
try {
Configure::config('default', new PhpConfig());
Configure::load('app', 'default', false);
} catch (\Exception $e) {
exit($e->getMessage() . "\n");
}
$TMP = new \Cake\Filesystem\Folder(TMP);
$TMP->create(TMP . 'cache/models', 0777);
$TMP->create(TMP . 'cache/persistent', 0777);
$TMP->create(TMP . 'cache/views', 0777);
$cache = [
'default' => [
'engine' => 'File',
],
'_cake_core_' => [
'className' => 'File',
'prefix' => '_cake_core_',
'path' => CACHE . 'persistent/',
'serialize' => true,
'duration' => '+10 seconds',
],
'_cake_model_' => [
'className' => 'File',
'prefix' => '_cake_model_',
'path' => CACHE . 'models/',
'serialize' => 'File',
'duration' => '+10 seconds',
],
'_cake_method_' => [
'className' => 'File',
'prefix' => '_cake_method_',
'path' => CACHE . 'models/',
'serialize' => 'File',
'duration' => '+10 seconds',
],
];
Cake\Cache\Cache::setConfig($cache);
if (file_exists($root . '/config/bootstrap.php')) {
require $root . '/config/bootstrap.php';
}
if (!getenv('db_dsn')) {
putenv('db_dsn=sqlite:///:memory:');
}
Cake\Datasource\ConnectionManager::setConfig('test', [
'url' => getenv('db_dsn'),
'timezone' => 'UTC'
]);
phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
colors="true"
stopOnFailure="false"
bootstrap="./tests/bootstrap.php"
>
<php>
<ini name="memory_limit" value="-1"/>
<ini name="apc.enable_cli" value="1"/>
</php>
<!-- Add any additional test suites you want to run here -->
<testsuites>
<testsuite name="YummySearch Test Suite">
<directory>./tests/TestCase</directory>
</testsuite>
</testsuites>
<!-- configure code coverage -->
<filter>
<whitelist>
<directory suffix=".php">./src/</directory>
</whitelist>
</filter>
<!-- Setup a listener for fixtures -->
<listeners>
<listener
class="Cake\TestSuite\Fixture\FixtureInjector">
<arguments>
<object class="Cake\TestSuite\Fixture\FixtureManager" />
</arguments>
</listener>
</listeners>
</phpunit>
getting error $wodb as Uncaught SyntaxError: Unexpected identifier
function store_db() {
global $wpdb; $fields = array('email');
$tbl_name = $wpdb->prefix.'feedback';
$kv_data = array( 's_email'=> $email) ;
$wpdb->insert( $tbl_name, $kv_data )
}
You should consider using an IDE such as Sublime Text, DreamWeaver, PHP Storm, etc. Any number of them would show you where the syntax error is. I pasted it into my IDE and it instantly told me there was a missing semi colon after this line $wpdb->insert( $tbl_name, $kv_data ).
Also you'll want to take care to manage your formatting/indentation - future you appreciates it!
function store_db() {
global $wpdb;
$field = array( 'email' );
$table = $wpdb->prefix.'feedback';
$kv_data = array( 's_email' => $email );
$wpdb->insert( $table, $kv_data ); // Added `;` to this line.
}
How can I populate/imitate server variables in PHPUnit Test cases using Symfony3?
I try to create functional tests for my symfony3 application.
I use LiipFunctionalTestBundle.
I have a special $_SERVER variable which contains the country of the visitor. The behavior of the action strongly depends on it.
I try to populate it in my test case.
Here is the content of the phpunit.xml.dist file which is based on Setting PHP INI settings, Constants and Global Variables in PHPUnit
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="app/autoload.php"
>
<php>
<ini name="error_reporting" value="-1" />
<server name="KERNEL_DIR" value="app/" />
<server name="COUNTRY_CODE" value="AT" />
<server name="HTTP_COUNTRY_CODE" value="AT" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
<exclude>
<directory>src/*Bundle/Resources</directory>
<directory>src/*/*Bundle/Resources</directory>
<directory>src/*/Bundle/*Bundle/Resources</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
$client = static::createClient(array(), array(
'PHP_AUTH_USER' => "test_login",
'PHP_AUTH_PW' => "test_password",
'HTTP_HOST' => "phpunit.symfony.dev",
'REQUEST_URI' => "/app/setting",
'DOCUMENT_ROOT' => "/path/to/docroot/app/web"
));
and
$this->client->request(
'GET',
'/app/profile',
array(),
array(),
array(
'COUNTRY_CODE' => "AT",
'HTTP_COUNTRY_CODE' => "AT",
'SCRIPT_NAME' => "thing/thong",
'HTTP_REFERER' => '/foo/bar'
)
);
when I get the request in the unittest by dump($this->client->getRequest()); then I see my variables:
Symfony\Component\HttpFoundation\Request {#1009
+attributes: Symfony\Component\HttpFoundation\ParameterBag {#1008
#parameters: []
}
+request: Symfony\Component\HttpFoundation\ParameterBag {#1093
#parameters: []
}
+query: Symfony\Component\HttpFoundation\ParameterBag {#1092
#parameters: []
}
+server: Symfony\Component\HttpFoundation\ServerBag {#993
#parameters: array:22 [
"PHP_AUTH_USER" => "test_login"
"PHP_AUTH_PW" => "test_password"
"SERVER_NAME" => "phpunit.symfony.dev"
"HTTP_HOST" => "phpunit.symfony.dev"
"REQUEST_URI" => "/app/setting"
"DOCUMENT_ROOT" => "/path/to/docroot/app/web"
"COUNTRY_CODE" => "AT"
"HTTP_COUNTRY_CODE" => "AT"
"SCRIPT_NAME" => "thing/thong"
"HTTP_REFERER" => "/foo/bar"
"SERVER_PORT" => 80
"HTTP_USER_AGENT" => "Symfony BrowserKit"
"HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
"HTTP_ACCEPT_LANGUAGE" => "en-us,en;q=0.5"
"HTTP_ACCEPT_CHARSET" => "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
"REMOTE_ADDR" => "127.0.0.1"
"SCRIPT_FILENAME" => ""
"SERVER_PROTOCOL" => "HTTP/1.1"
"REQUEST_TIME" => 1485369277
"PATH_INFO" => ""
"REQUEST_METHOD" => "GET"
"QUERY_STRING" => ""
]
}
but for some reason, in the action
public function indexAction(Request $request)
{
dump($_SERVER);
}
the $_SERVER variable contains the Shell and Environmental Variables instead:
"LESSOPEN" => "| /usr/bin/lesspipe %s"
"PROFILEHOME" => ""
"GNOME_KEYRING_PID" => ""
"USER" => "developer"
"LANGUAGE" => "en_US"
"UPSTART_INSTANCE" => ""
"XDG_SEAT" => "seat0"
"SESSION" => "sess$58479"
"XDG_SESSION_TYPE" => "x11"
"SHLVL" => "2"
"HOME" => "/home/developer"
"DESKTOP_SESSION" => "sess$58479"
"QT_LINUX_ACCESSIBILITY_ALWAYS_ON" => "1"
"SHELL_SESSION_ID" => "78c26972fe6040009409a2bd8748034d"
"GTK_MODULES" => "gail:atk-bridge:unity-gtk-module"
"XDG_SEAT_PATH" => "/org/freedesktop/DisplayManager/Seat0"
"KONSOLE_DBUS_SESSION" => "/Sessions/1"
What do I do wrong?
Is there any way to imitate the server variables in command line, using Symfony3 and phpunit?
I was on a wrong way. I can access the server variables through the $request object:
public function indexAction(Request $request)
{
dump($request->server->get('HTTP_HOST'));
dump($request->server->get('COUNTRY_CODE'));
}
Can anyone tell me why this is not working?
The drupal_render(drupal_get_form) is dynamically created in a foreach loop and put into a table theme.
Everything loads except the form fields. I've tried debugging by adding echos and exits to each form function call, but the page continues to load. I am not sure if these functions are simply not being called or if there is some other issue.
foreach( $w as $k => $v ) {
$r[] = array(
'$'.number_format($v->amount, 2),
date('F d, Y', $v->created),
filter_xss($v->paypal_email),
drupal_render(drupal_get_form(('toefl_tutors_admin_withdrawl_request_form_'.$v->id), $v->id))
);
}
function toefl_tutors_admin_withdrawl_request_forms($form_id, $args) {
$forms = array();
if (!empty($args) && $form_id == 'toefl_tutors_admin_withdrawl_request_form_' . $args[0]) {
$forms[$form_id] = array(
'callback' => 'toefl_tutors_admin_withdrawl_request_form',
'callback arguments' => array($args[0]),
);
}
return $forms;
}
function toefl_tutors_admin_withdrawl_request_form($form, &$form_state, $id = 0) {
$form['twid'] = array(
'#type' => 'hidden',
'#value' => $id
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Send Money'),
'#attributes' => array('class' => array('btn', 'btn-success'))
);
return $form;
}
I've solved the problem.
I needed to rename the hook_forms function to toefl_tutors_forms() because My module name is actually toefl_tutors not toefl_tutors_admin_withdrawl_request
Apparently and correct me if I am wrong, in order to use hook_forms you must name it mymodulename_forms, not mymodulename_xx_forms.
What confused me was hook_form works perfectly when you name the form function mymodulename_xx_form().
I created a gallery post type (as part of a plugin) that contains besides a title and some meta information also a wp_list_table that queries those attachments which have the current post as post_parent. I ran into a problem when suddenly my publish button stopped working. No matter if I'm creating a new gallery or if I'm editing an old one, once I click on update/publish my changes get lost and I end up on edit.php.
Anybody knows what that's all about?
I where able to figure out where the problem seems to be. It's in my list_table class which inherits from wp_list_table. after commenting out some unimportant functions i ended up with a different error but still no new or updated gallery. Now I get the are you sure you want to do this page.
Even the most basic class won't work...
if( ! class_exists( 'WP_List_Table' ) ) {
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
class Yard_Attachment_Table extends WP_List_Table {
function __construct() {
global $status, $page;
parent::__construct( array(
'singular' => 'yard Attachment',
'plural' => 'yard Attachments',
'ajax' => false
) );
}
function column_default($item, $column_name) {
return 'default';
}
function get_columns(){
$columns = array(
'checkbox' => '<input type="checkbox" />', //for simplicity its not 'cb'
'thumb' => 'Thumbnail',
'title' => 'Titel',
'pos' => 'Position'
);
return $columns;
}
function prepare_items() {
global $wpdb;
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array($columns, $hidden, $sortable);
if (isset($_REQUEST['post'])) {
$query = " SELECT *
FROM $wpdb->posts
WHERE post_type = 'attachment'
AND post_parent = {$_REQUEST['post']}";
$data = $wpdb->get_results($query, ARRAY_A);
} else {
$data = array();
}
$this->items = $data;
}
}
In the plugin class' constructor I use
add_action('add_meta_boxes_yard_gallery', array($this, 'yard_metaboxes'));.
In yard_metaboxes I use add_meta_box and in the function I have as a callback i'm creating a new instance of my table class and I call prepare_items() and display()
Turning error_reporting on my page dies with these messages:
Strict Standards: Only variables should be passed by reference in /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pomo/mo.php on line 210
Warning: Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pomo/mo.php:210) in /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pluggable.php on line 876
BTW I'm not localizing.
Please help! If i had more reputation I'd offer it.
Adding the meta box code
in my plugin file:
require_once( plugin_dir_path( __FILE__ ) . 'class-yard.php' );
Yard::get_instance();
in my class-yard file the meta box methods are at the bottom:
class Yard {
protected static $instance = null;
private function __construct() {
include_once('class-yard-attachments.php');
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_styles' ) );
add_action('after_setup_theme', array($this, 'yard_thumbnails'));
add_action('init', array($this, 'yard_post_type'));
add_action('init', array($this, 'yard_taxonomies'));
add_filter('manage_yard_gallery_posts_columns', array($this, 'yard_add_columns'));
add_action('manage_posts_custom_column', array($this, 'yard_fill_columns'));
add_action('add_meta_boxes_yard_gallery', array($this, 'yard_metaboxes'));
}
public static function get_instance() {// If the single instance hasn't been set, set it now.
if (null == self::$instance ) {
self::$instance = new self;
}
return self::$instance;
}
public function enqueue_admin_styles() {
$screen = get_current_screen();
if ($screen->post_type == 'yard_gallery') {
wp_register_style( 'yard-gallery-style', plugins_url('css/yard-gallery-style.css', __FILE__) );
wp_enqueue_style( 'yard-gallery-style' );
}
}
public function yard_thumbnails() {
//add_image_size('yard-thumbnail', 100, 100, true);
}
public function yard_post_type() {
$gallery_labels = array(
'name' => 'Galerien',
'singular_name' => 'Galerie',
'all_items' => 'Alle Galerien',
'add_new' => 'Erstellen',
'add_new_item' => 'Neue Galerie erstellen',
'edit_item' => 'Galerie bearbeiten',
'new_item' => 'Neue Galerie',
'view' => 'Galerie anzeigen',
'view_item' => 'Gallerie anzeigen',
'search_items' => 'Galerie durchsuchen',
'not_found' => 'Keine Galerien gefunden',
'not_found_in_trash' => 'Es befinden sich keine Galerien im Papierkorb',
'parent_item_colon' => ''
);
$gallery_args = array(
'labels' => $gallery_labels,
'public' => true,
// 'publicly_queryable' => true,
// 'show_ui' => true,
// 'show_in_menu' => true,
// 'query_var' => true,
'rewrite' => true,
// 'capability_type' => 'post',
// 'hierarchical' => false,
'menu_position' => 12,
'supports' => array(
'title'
)
// 'menu_icon' => plugin_dir_url(__FILE__) . '/assets/icon_16_grey.png'//16x16 png if you want an icon
);
register_post_type('yard_gallery', $gallery_args);
}
public function yard_taxonomies() {
register_taxonomy(
'yard_work_type',
'yard_gallery',
array(
'hierarchical' => true,
'label' => 'Art der Arbeit'
)
);
register_taxonomy(
'yard_subject',
'yard_gallery',
array(
'hierarchical' => true,
'label' => 'Motiv'
)
);
}
public function yard_add_columns( $columns ){
$columns = array(
'cb' => '<input type="checkbox">',
'yard_post_thumb' => 'Thumbnail',
'title' => 'Bezeichnung',
'yard_pos' => 'Position',
'date' => 'Datum'
);
return $columns;
}
public function yard_fill_columns( $column ) {
global $post;
switch ($column) {
case 'yard_post_thumb' :
echo the_post_thumbnail('admin-list-thumb');
break;
}
}
public function yard_metaboxes( $post ) {
global $wp_meta_boxes;
add_meta_box(
'yard-attachments',
'Bilder',
array($this, 'get_yard_attachment_table'),
'yard_gallery'
);
}
public function get_yard_attachment_table() {
$yard_list_table = new Yard_Attachment_Table();
$yard_list_table->prepare_items();
$yard_list_table->display();
}
}
Strict Standards: Only variables should be passed by reference in /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pomo/mo.php on line 210
The error message tells it all. The ".../popo/mo.php" file has to do with (is related to) the Wordpress translation. (I bet you're using Wordpress with German language files).
I can't see what could be wrong in the code you've posted here, but something is interfering with translation. Looking at what the error message tells us, some variable that Wordpress tries to translate fails to be translated since it's not the correct type.
Warning: Cannot modify header information - headers already sent by (output started at /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pomo/mo.php:210) in /Applications/MAMP/htdocs/Web/ChristophRokitta/wp v.1.0/wp-includes/pluggable.php on line 876
This is a logic result of the previous error message and the headers Wordpress tries to send to the browser.
What's happening: the first error message is being pushed to the client and flushed to the browser screen. Next, Wordpress tries to send it's usual headers and produces an error while doing so because headers have to be send before ANY content is being send to the client.
In other words: the "Cannot modify header information" error always comes up when you echo something to screen and then try to send "header(...)" information. In this case, the translation problem produces the first error message and then Wordpress tries to send headers, which fails and produces the second error message.
TIPS
Check everything you're doing which is related to translation (read: wherever you are passing "German" and/or "English" language strings)
and even more important
Make sure that you're actually passing the correct type(s)... looking at the error and your code, it could well be you're passing a class, a class reference, or another object somewhere instead of the expected variable.