Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move C3 code to separate class (2023) #85

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

marcovtwout
Copy link

This PR is a first step in improving #40 applying the same solution as #72
Instead of having a copy of c3.php in the project root it can be included from any location.

Basic usage:

require __DIR__ . '/vendor/autoload.php'; // If using Composer
//require __DIR__ . '/vendor/codeception/c3/c3.php'; // Or include it directly

$c3 = new Codeception\C3(__DIR__); // pass the directory that contains Codeception config files
$c3->run();

I only made the minimal changes to use this concept. Best to disable whitespace comparison when reviewing this PR.

There's more to be improved after this:

  • Since this probably means a new major version of c3, we could remove legacy options for outdated autoloading, codeception and phpunit versions
  • Add options to configure error log file and temp output directory
  • Make all __c3_-functions part of the class
  • Restructure remaining code blocks into functions

But please review this PR first and decide if this could start a new v3 branch. If so, I'd be happy to submit further improvement PR's on top of that (based on main...marcovtwout:c3:class_based_c3_improvements).

@marcovtwout
Copy link
Author

@Naktibalda Do you need any help getting this reviewed? I think it would be really benificial for the maintainability of this project if it becomes a composer requirement through this PR.

@marcovtwout
Copy link
Author

@TavoNiievez Is there anyone else that can review this?

@delboy1978uk
Copy link

@marcovtwout looks good (haven't tried it), you should resolve conflicts and update this line for the tests here with the latest PHP versions, and drop the ones that are no longer supported https://github.com/Codeception/c3/blob/main/.github/workflows/main.yml#L11
Official support for PHP 8.0 ends in January https://www.php.net/supported-versions.php

@marcovtwout
Copy link
Author

@delboy1978uk That line is not part of this PR, but I can rebase and fix conflicts again and again.. but there is no point until somebody reviews this first.

So can somebody please review this? :)


if (isset($_COOKIE['CODECEPTION_CODECOVERAGE'])) {
$cookie = json_decode($_COOKIE['CODECEPTION_CODECOVERAGE'], true);
// $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'] = 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this one was there as a configuration option. How to configure it now if the file isn't yours?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This (commented) code was only moved from above the use-statements to below. Functionality is unchanged.

Copy link

@SamMousa SamMousa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've given a lot of detailed comments and they could lead to the following conclusion:

  • This new release will be a backwards compatibility break
  • We could use this to drop support for older versions of Codeception / PHPUnit

Most if this code is very old and therefore very messy. It could be immensely simplified:

  • Remove constants, use constructor arguments for configuration
  • Remove workarounds for class loading, it's 2023, we use composer autoloader, with additional support for Codeception PHAR.

Additionally, I'm not sure why we need to load codeception configuration at all, or need codeception classes for that matter. Couldn't we just rewrite this as a thin wrapper on the code coverage package which has been improved since C3 was originally written?

Comment on lines +46 to +48
public function setAutoloadRootDir($dir)
{
$this->autoloadRootDir = $dir;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the autoloadRootDir should be mutable. I'm not even sure it's needed at all in this class.

ini_set('memory_limit', $requiredMemory);
}
// Autoload Codeception classes
if (!class_exists('\\Codeception\\Codecept') || !function_exists('codecept_is_path_absolute')) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use ::class (and add import at top)

Suggested change
if (!class_exists('\\Codeception\\Codecept') || !function_exists('codecept_is_path_absolute')) {
if (!class_exists(Codecept::class) || !function_exists('codecept_is_path_absolute')) {

Comment on lines +102 to +103
} elseif (stream_resolve_include_path($this->autoloadRootDir . '/vendor/autoload.php')) {
require_once $this->autoloadRootDir . '/vendor/autoload.php';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should never include the composer autoloader, since it's responsible for loading our class. So I'd say remvoe this code path.

The only thing we should manually autoload are:

  • Codeception from phar file

Comment on lines +105 to +109
if (stream_resolve_include_path($this->autoloadRootDir . '/vendor/codeception/codeception/autoload.php')) {
require_once $this->autoloadRootDir . '/vendor/codeception/codeception/autoload.php';
}
} elseif (stream_resolve_include_path('Codeception/autoload.php')) {
require_once 'Codeception/autoload.php';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From inspecting that file I don't think we actually need to include it: https://github.com/Codeception/Codeception/blob/5.0/autoload.php

define('C3_CODECOVERAGE_PROJECT_ROOT', Codeception\Configuration::projectDir());
define('C3_CODECOVERAGE_TESTNAME', $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE']);
// phpunit codecoverage shimming
if (!class_exists('PHP_CodeCoverage') and class_exists('SebastianBergmann\CodeCoverage\CodeCoverage')) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class no longer exist (it was removed ~2012) from PHPUnit. I propose not supporting it in this new version of C3. Just remove this shimming.

Comment on lines +135 to +137
if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG'])) {
$configFile = $this->configDir . DIRECTORY_SEPARATOR . $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG'];
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm personally not a fan of having this artifact in the code. We should not be dynamically loading user supplied paths.
I imagine this is a very niche cache where you want to dynamically configure it for C3 based on the request.

$requestedC3Report = (strpos($_SERVER['REQUEST_URI'], 'c3/report') !== false);
function __c3_clear()
{
\Codeception\Util\FileSystem::doEmptyDir(C3_CODECOVERAGE_MEDIATE_STORAGE);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not be using this constant.
Instead:

  • define it as a constructor argument
  • store it in a private property
  • in the constructor check if the constant is defined and if so use it to initialize the private property
  • remove all references to this constant

if ($cookie) {
foreach ($cookie as $key => $value) {
if (!empty($value)) {
$_SERVER["HTTP_X_CODECEPTION_" . strtoupper($key)] = $value;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use the global $_SERVER instead add a constructor param $server.
This makes the dependencies clear from the call signature:

(new C3($_SERVER, $_REQUEST, $argument1, ...))->run();

@marcovtwout
Copy link
Author

@SamMousa Thanks for your review!

I agree exactly with your conclusions, but I have split them up into two parts for the sake of easier reviewing and continued development:

  • Step 1, create a new major version based on this PR so we can use it as a Composer dependency. The result could already be used by anyone with existing setups, with only a minimal change in your projects and low risk of breaking things.
  • Step 2, start development on the next major version to get rid of many legacy options and improve code quality. For a great part my suggestions overlap with yours. See the commits I created on this derived branch: main...marcovtwout:c3:class_based_c3_improvements

@SamMousa
Copy link

Cool, go ahead with step 1 then. For the new implementation I'd say have a look at #93! If you want to give hte implementation a try go ahead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants