Introduce wp scaffold theme-tests for scaffolding theme unit tests

This commit is contained in:
Daniel Bachhuber 2016-11-11 05:49:33 -08:00
parent d790b6cc4c
commit 358ef43b62
8 changed files with 320 additions and 123 deletions

View file

@ -0,0 +1,95 @@
Feature: Scaffold plugin unit tests

Scenario: Scaffold plugin tests
Given a WP install
When I run `wp plugin path`
Then save STDOUT as {PLUGIN_DIR}

When I run `wp scaffold plugin hello-world --skip-tests`
Then STDOUT should not be empty
And the {PLUGIN_DIR}/hello-world/.editorconfig file should exist
And the {PLUGIN_DIR}/hello-world/hello-world.php file should exist
And the {PLUGIN_DIR}/hello-world/readme.txt file should exist
And the {PLUGIN_DIR}/hello-world/tests directory should not exist

When I run `wp scaffold plugin-tests hello-world`
Then STDOUT should not be empty
And the {PLUGIN_DIR}/hello-world/tests directory should contain:
"""
bootstrap.php
test-sample.php
"""
And the {PLUGIN_DIR}/hello-world/tests/bootstrap.php file should contain:
"""
require dirname( dirname( __FILE__ ) ) . '/hello-world.php';
"""
And the {PLUGIN_DIR}/hello-world/tests/bootstrap.php file should contain:
"""
* @package Hello_World
"""
And the {PLUGIN_DIR}/hello-world/tests/test-sample.php file should contain:
"""
* @package Hello_World
"""
And the {PLUGIN_DIR}/hello-world/bin directory should contain:
"""
install-wp-tests.sh
"""
And the {PLUGIN_DIR}/hello-world/phpunit.xml.dist file should exist
And the {PLUGIN_DIR}/hello-world/phpcs.ruleset.xml file should exist
And the {PLUGIN_DIR}/hello-world/circle.yml file should not exist
And the {PLUGIN_DIR}/hello-world/.gitlab-ci.yml file should not exist
And the {PLUGIN_DIR}/hello-world/.travis.yml file should contain:
"""
script:
- phpcs --standard=phpcs.ruleset.xml $(find . -name '*.php')
- phpunit
"""

When I run `wp eval "if ( is_executable( '{PLUGIN_DIR}/hello-world/bin/install-wp-tests.sh' ) ) { echo 'executable'; } else { exit( 1 ); }"`
Then STDOUT should be:
"""
executable
"""

Scenario: Scaffold plugin tests with Circle as the provider, part one
Given a WP install
And I run `wp scaffold plugin hello-world --ci=circle`

When I run `wp plugin path hello-world --dir`
Then save STDOUT as {PLUGIN_DIR}
And the {PLUGIN_DIR}/.travis.yml file should not exist
And the {PLUGIN_DIR}/circle.yml file should contain:
"""
version: 5.6.22
"""

Scenario: Scaffold plugin tests with Circle as the provider, part two
Given a WP install
And I run `wp scaffold plugin hello-world --skip-tests`

When I run `wp plugin path hello-world --dir`
Then save STDOUT as {PLUGIN_DIR}

When I run `wp scaffold plugin-tests hello-world --ci=circle`
Then STDOUT should not be empty
And the {PLUGIN_DIR}/.travis.yml file should not exist
And the {PLUGIN_DIR}/circle.yml file should contain:
"""
version: 5.6.22
"""

Scenario: Scaffold plugin tests with Gitlab as the provider
Given a WP install
And I run `wp scaffold plugin hello-world --skip-tests`

When I run `wp plugin path hello-world --dir`
Then save STDOUT as {PLUGIN_DIR}

When I run `wp scaffold plugin-tests hello-world --ci=gitlab`
Then STDOUT should not be empty
And the {PLUGIN_DIR}/.travis.yml file should not exist
And the {PLUGIN_DIR}/.gitlab-ci.yml file should contain:
"""
MYSQL_DATABASE
"""

View file

@ -0,0 +1,75 @@
Feature: Scaffold theme unit tests

Background:
Given a WP install
And I run `wp theme install p2`
And I run `wp scaffold child-theme p2child --parent_theme=p2`

When I run `wp theme path`
Then save STDOUT as {THEME_DIR}

Scenario: Scaffold theme tests
When I run `wp scaffold theme-tests p2child`
Then STDOUT should not be empty
And the {THEME_DIR}/p2child/tests directory should contain:
"""
bootstrap.php
test-sample.php
"""
And the {THEME_DIR}/p2child/tests/bootstrap.php file should contain:
"""
register_theme_directory( dirname( $theme_dir ) );
"""
And the {THEME_DIR}/p2child/tests/bootstrap.php file should contain:
"""
* @package P2child
"""
And the {THEME_DIR}/p2child/tests/test-sample.php file should contain:
"""
* @package P2child
"""
And the {THEME_DIR}/p2child/bin directory should contain:
"""
install-wp-tests.sh
"""
And the {THEME_DIR}/p2child/phpunit.xml.dist file should exist
And the {THEME_DIR}/p2child/phpcs.ruleset.xml file should exist
And the {THEME_DIR}/p2child/circle.yml file should not exist
And the {THEME_DIR}/p2child/.gitlab-ci.yml file should not exist
And the {THEME_DIR}/p2child/.travis.yml file should contain:
"""
script:
- phpcs --standard=phpcs.ruleset.xml $(find . -name '*.php')
- phpunit
"""

When I run `wp eval "if ( is_executable( '{THEME_DIR}/p2child/bin/install-wp-tests.sh' ) ) { echo 'executable'; } else { exit( 1 ); }"`
Then STDOUT should be:
"""
executable
"""

Scenario: Scaffold theme tests invalid theme
When I try `wp scaffold theme-tests p3child`
Then STDERR should be:
"""
Error: Invalid theme slug specified.
"""

Scenario: Scaffold theme tests with Circle as the provider
When I run `wp scaffold theme-tests p2child --ci=circle`
Then STDOUT should not be empty
And the {THEME_DIR}/p2child/.travis.yml file should not exist
And the {THEME_DIR}/p2child/circle.yml file should contain:
"""
version: 5.6.22
"""

Scenario: Scaffold theme tests with Gitlab as the provider
When I run `wp scaffold theme-tests p2child --ci=gitlab`
Then STDOUT should not be empty
And the {THEME_DIR}/p2child/.travis.yml file should not exist
And the {THEME_DIR}/p2child/.gitlab-ci.yml file should contain:
"""
MYSQL_DATABASE
"""

View file

@ -271,100 +271,6 @@ Feature: WordPress code scaffolding
Plugin 'hello-world' network activated.
"""

Scenario: Scaffold plugin tests
Given a WP install
When I run `wp plugin path`
Then save STDOUT as {PLUGIN_DIR}

When I run `wp scaffold plugin hello-world --skip-tests`
Then STDOUT should not be empty
And the {PLUGIN_DIR}/hello-world/.editorconfig file should exist
And the {PLUGIN_DIR}/hello-world/hello-world.php file should exist
And the {PLUGIN_DIR}/hello-world/readme.txt file should exist
And the {PLUGIN_DIR}/hello-world/tests directory should not exist

When I run `wp scaffold plugin-tests hello-world`
Then STDOUT should not be empty
And the {PLUGIN_DIR}/hello-world/tests directory should contain:
"""
bootstrap.php
test-sample.php
"""
And the {PLUGIN_DIR}/hello-world/tests/bootstrap.php file should contain:
"""
require dirname( dirname( __FILE__ ) ) . '/hello-world.php';
"""
And the {PLUGIN_DIR}/hello-world/tests/bootstrap.php file should contain:
"""
* @package Hello_World
"""
And the {PLUGIN_DIR}/hello-world/tests/test-sample.php file should contain:
"""
* @package Hello_World
"""
And the {PLUGIN_DIR}/hello-world/bin directory should contain:
"""
install-wp-tests.sh
"""
And the {PLUGIN_DIR}/hello-world/phpunit.xml.dist file should exist
And the {PLUGIN_DIR}/hello-world/phpcs.ruleset.xml file should exist
And the {PLUGIN_DIR}/hello-world/circle.yml file should not exist
And the {PLUGIN_DIR}/hello-world/.gitlab-ci.yml file should not exist
And the {PLUGIN_DIR}/hello-world/.travis.yml file should contain:
"""
script:
- phpcs --standard=phpcs.ruleset.xml $(find . -name '*.php')
- phpunit
"""

When I run `wp eval "if ( is_executable( '{PLUGIN_DIR}/hello-world/bin/install-wp-tests.sh' ) ) { echo 'executable'; } else { exit( 1 ); }"`
Then STDOUT should be:
"""
executable
"""

Scenario: Scaffold plugin tests with Circle as the provider, part one
Given a WP install
And I run `wp scaffold plugin hello-world --ci=circle`

When I run `wp plugin path hello-world --dir`
Then save STDOUT as {PLUGIN_DIR}
And the {PLUGIN_DIR}/.travis.yml file should not exist
And the {PLUGIN_DIR}/circle.yml file should contain:
"""
version: 5.6.22
"""

Scenario: Scaffold plugin tests with Circle as the provider, part two
Given a WP install
And I run `wp scaffold plugin hello-world --skip-tests`

When I run `wp plugin path hello-world --dir`
Then save STDOUT as {PLUGIN_DIR}

When I run `wp scaffold plugin-tests hello-world --ci=circle`
Then STDOUT should not be empty
And the {PLUGIN_DIR}/.travis.yml file should not exist
And the {PLUGIN_DIR}/circle.yml file should contain:
"""
version: 5.6.22
"""

Scenario: Scaffold plugin tests with Gitlab as the provider
Given a WP install
And I run `wp scaffold plugin hello-world --skip-tests`

When I run `wp plugin path hello-world --dir`
Then save STDOUT as {PLUGIN_DIR}

When I run `wp scaffold plugin-tests hello-world --ci=gitlab`
Then STDOUT should not be empty
And the {PLUGIN_DIR}/.travis.yml file should not exist
And the {PLUGIN_DIR}/.gitlab-ci.yml file should contain:
"""
MYSQL_DATABASE
"""

Scenario: Scaffold starter code for a theme
Given a WP install
Given I run `wp theme path`

View file

@ -587,44 +587,109 @@ class Scaffold_Command extends WP_CLI_Command {
*
* @subcommand plugin-tests
*/
function plugin_tests( $args, $assoc_args ) {
public function plugin_tests( $args, $assoc_args ) {
$this->scaffold_plugin_theme_tests( $args, $assoc_args, 'plugin' );
}

/**
* Generate files needed for running PHPUnit tests in a theme.
*
* The following files are generated by default:
*
* * `phpunit.xml.dist` is the configuration file for PHPUnit.
* * `.travis.yml` is the configuration file for Travis CI. Use `--ci=<provider>` to select a different service.
* * `bin/install-wp-tests.sh` configures the WordPress test suite and a test database.
* * `tests/bootstrap.php` is the file that makes the current theme active when running the test suite.
* * `tests/test-sample.php` is a sample file containing the actual tests.
* * `phpcs.ruleset.xml` is a collenction of PHP_CodeSniffer rules.
*
* Learn more from the [plugin unit tests documentation](http://wp-cli.org/docs/plugin-unit-tests/).
*
* ## ENVIRONMENT
*
* The `tests/bootstrap.php` file looks for the WP_TESTS_DIR environment
* variable.
*
* ## OPTIONS
*
* [<theme>]
* : The name of the theme to generate test files for.
*
* [--dir=<dirname>]
* : Generate test files for a non-standard theme path. If no theme slug is specified, the directory name is used.
*
* [--ci=<provider>]
* : Choose a configuration file for a continuous integration provider.
* ---
* default: travis
* options:
* - travis
* - circle
* - gitlab
* ---
*
* [--force]
* : Overwrite files that already exist.
*
* ## EXAMPLES
*
* # Generate unit test files for theme 'twentysixteenchild'.
* $ wp scaffold theme-tests twentysixteenchild
* Success: Created test files.
*
* @subcommand theme-tests
*/
public function theme_tests( $args, $assoc_args ) {
$this->scaffold_plugin_theme_tests( $args, $assoc_args, 'theme' );
}

private function scaffold_plugin_theme_tests( $args, $assoc_args, $type ) {
$wp_filesystem = $this->init_wp_filesystem();

if ( ! empty( $args[0] ) ) {
$plugin_slug = $args[0];
$plugin_dir = WP_PLUGIN_DIR . "/$plugin_slug";
if ( empty( $assoc_args['dir'] ) && ! is_dir( $plugin_dir ) ) {
WP_CLI::error( 'Invalid plugin slug specified.' );
$slug = $args[0];
if ( 'theme' === $type ) {
$theme = wp_get_theme( $slug );
if ( $theme->exists() ) {
$target_dir = $theme->get_stylesheet_directory();
} else {
WP_CLI::error( "Invalid {$type} slug specified." );
}
} else {
$target_dir = WP_PLUGIN_DIR . "/$slug";
}
if ( empty( $assoc_args['dir'] ) && ! is_dir( $target_dir ) ) {
WP_CLI::error( "Invalid {$type} slug specified." );
}
}

if ( ! empty( $assoc_args['dir'] ) ) {
$plugin_dir = $assoc_args['dir'];
if ( ! is_dir( $plugin_dir ) ) {
WP_CLI::error( 'Invalid plugin directory specified.' );
$target_dir = $assoc_args['dir'];
if ( ! is_dir( $target_dir ) ) {
WP_CLI::error( "Invalid {$type} directory specified." );
}
if ( empty( $plugin_slug ) ) {
$plugin_slug = basename( $plugin_dir );
if ( empty( $slug ) ) {
$slug = basename( $target_dir );
}
}

if ( empty( $plugin_slug ) || empty( $plugin_dir ) ) {
WP_CLI::error( 'Invalid plugin specified.' );
if ( empty( $slug ) || empty( $target_dir ) ) {
WP_CLI::error( "Invalid {$type} specified." );
}

$plugin_name = ucwords( str_replace( '-', ' ', $plugin_slug ) );
$plugin_package = str_replace( ' ', '_', $plugin_name );
$name = ucwords( str_replace( '-', ' ', $slug ) );
$package = str_replace( ' ', '_', $name );

$tests_dir = "$plugin_dir/tests";
$bin_dir = "$plugin_dir/bin";
$tests_dir = "{$target_dir}/tests";
$bin_dir = "{$target_dir}/bin";

$wp_filesystem->mkdir( $tests_dir );
$wp_filesystem->mkdir( $bin_dir );

$wp_versions_to_test = array('latest');
// Parse plugin readme.txt
if ( file_exists( $plugin_dir . '/readme.txt' ) ) {
$readme_content = file_get_contents( $plugin_dir . '/readme.txt' );
if ( file_exists( $target_dir . '/readme.txt' ) ) {
$readme_content = file_get_contents( $target_dir . '/readme.txt' );

preg_match( '/Requires at least\:(.*)\n/m', $readme_content, $matches );
if ( isset( $matches[1] ) && $matches[1] ) {
@ -636,36 +701,38 @@ class Scaffold_Command extends WP_CLI_Command {
}
}

$plugin_data = array(
'plugin_slug' => $plugin_slug,
'plugin_package' => $plugin_package,
$template_data = array(
"{$type}_slug" => $slug,
"{$type}_package" => $package,
);

$force = \WP_CLI\Utils\get_flag_value( $assoc_args, 'force' );
$files_to_create = array(
"$tests_dir/bootstrap.php" => Utils\mustache_render( 'bootstrap.mustache', $plugin_data ),
"$tests_dir/test-sample.php" => Utils\mustache_render( 'test-sample.mustache', $plugin_data ),
"$tests_dir/bootstrap.php" => Utils\mustache_render( "{$type}-bootstrap.mustache", $template_data ),
"$tests_dir/test-sample.php" => Utils\mustache_render( "{$type}-test-sample.mustache", $template_data ),
);
if ( 'travis' === $assoc_args['ci'] ) {
$files_to_create["$plugin_dir/.travis.yml"] = Utils\mustache_render( 'plugin-travis.mustache', compact( 'wp_versions_to_test' ) );
$files_to_create["{$target_dir}/.travis.yml"] = Utils\mustache_render( 'plugin-travis.mustache', compact( 'wp_versions_to_test' ) );
} else if ( 'circle' === $assoc_args['ci'] ) {
$files_to_create["$plugin_dir/circle.yml"] = Utils\mustache_render( 'plugin-circle.mustache' );
$files_to_create["{$target_dir}/circle.yml"] = Utils\mustache_render( 'plugin-circle.mustache' );
} else if ( 'gitlab' === $assoc_args['ci'] ) {
$files_to_create["$plugin_dir/.gitlab-ci.yml"] = Utils\mustache_render( 'plugin-gitlab.mustache' );
$files_to_create["{$target_dir}/.gitlab-ci.yml"] = Utils\mustache_render( 'plugin-gitlab.mustache' );
}
$files_written = $this->create_files( $files_to_create, $force );

$to_copy = array(
'install-wp-tests.sh' => $bin_dir,
'phpunit.xml.dist' => $plugin_dir,
'phpcs.ruleset.xml' => $plugin_dir,
'phpunit.xml.dist' => $target_dir,
'phpcs.ruleset.xml' => $target_dir,
);

foreach ( $to_copy as $file => $dir ) {
$file_name = "$dir/$file";
$force = \WP_CLI\Utils\get_flag_value( $assoc_args, 'force' );
$should_write_file = $this->prompt_if_files_will_be_overwritten( $file_name, $force );
if ( ! $should_write_file ) continue;
if ( ! $should_write_file ) {
continue;
}
$files_written[] = $file_name;

$wp_filesystem->copy( WP_CLI_ROOT . "/templates/$file", $file_name, true );

View file

@ -0,0 +1,34 @@
<?php
/**
* PHPUnit bootstrap file
*
* @package {{theme_package}}
*/

$_tests_dir = getenv( 'WP_TESTS_DIR' );
if ( ! $_tests_dir ) {
$_tests_dir = '/tmp/wordpress-tests-lib';
}

// Give access to tests_add_filter() function.
require_once $_tests_dir . '/includes/functions.php';

function _register_theme() {

$theme_dir = dirname( dirname( __FILE__ ) );
$current_theme = basename( $theme_dir );

register_theme_directory( dirname( $theme_dir ) );

add_filter( 'pre_option_template', function() use ( $current_theme ) {
return $current_theme;
});
add_filter( 'pre_option_stylesheet', function() use ( $current_theme ) {
return $current_theme;
});
}
tests_add_filter( 'muplugins_loaded', '_register_theme' );


// Start up the WP testing environment.
require $_tests_dir . '/includes/bootstrap.php';

View file

@ -0,0 +1,20 @@
<?php
/**
* Class SampleTest
*
* @package {{theme_package}}
*/

/**
* Sample test case.
*/
class SampleTest extends WP_UnitTestCase {

/**
* A single example test.
*/
function test_sample() {
// Replace this with some actual testing code.
$this->assertTrue( true );
}
}