atoum / AtoumBundle

This bundle provides a simple integration of atoum into Symfony 2.
MIT License
44 stars 25 forks source link

Support for tests outside of bundle. #65

Closed flip111 closed 10 years ago

flip111 commented 10 years ago

I have placed a class outside of a bundle (because it spans several classes) but atoum errors on this with the message: Tested class 'MyVendor\MyBundle\Entity\MyEntity' does not exist for test class 'MyVendor\MyBundle\Tests\Units\Entity\MyEntity'

Actual class is in: MyVendor\Entity\MyEntity.

I used the correct namespace in the test itself to make the class under test, so this is not a problem.

jdecool commented 10 years ago

What about this issue ?

Is it possible to test classes which are outside a bundle (in a component directory for example) ?

jubianchi commented 10 years ago

If your autoloader is configurerd correctly, there should not be any problem.

If you put classes outside of a normalized directory structure (do not respect PSR for example), atoum won't be able to guess the right path: it's not its job, it relies on the active autoloader to do that, be it composer one or atoum one). In any cas, you have to correctly setup your autoloader.

@flip111 it seems your class or test is wrong. As you said, your class lays in MyVendor\Entity\MyEntity but your test points to a MyVendor\MyBundle\Entity\MyEntity class. Those two paths are not compliant: one of them is inside a bundle, the other is not. You have to change your test.

@jdecool to me, there is no issue here. Just an autoloader misconfiguration.

Closing this, and letting you comment if it needs to be reopened.

flip111 commented 10 years ago

I don't have access to the original source code right now. But i don't think it's the job of the autoloader to find the corresponding class of the test !

Again: test: MyVendor\MyBundle\Tests\Units\Entity\MyEntity

now something (???) looks for a corresponding class of this test. Not the autoloader because it only finds when something tells it to find a class. Then something (???) figures out this class should be located here: MyVendor\MyBundle\Entity\MyEntity. But i don't want to have this directory structure pattern where original class & test are like this. So i define my own use statement for class: MyVendor\Entity\MyEntity and put this class under test.

So perhaps this could be split up into two questions:

  1. why does atoum even need to know the location of class under test when you still have to define it in the test anyway (creating a new instance with new). I don't think this should be the default behavior and
  2. how to turn this off so you can point to any class you want.

PSR had been setup correctly: namespaces match folder structure

jubianchi commented 10 years ago

@flip111

But i don't think it's the job of the autoloader to find the corresponding class of the test !

And I think you are wrong : if its not the autoload job to find classes, then what is it made for ? atoum's job is to run tests not explore directories to find classes. atoum provides an autoloader for you if you want to use it.

why does atoum even need to know the location of class under test when you still have to define it in the test anyway (creating a new instance with new)

Instanciating a class and loading it are two distinct actions : in a php script, are you able to instanciate a class without requireing or require_onceing it ? No! Loading the class' file is the autoloader job.

how to turn this off so you can point to any class you want.

Just require_once your class in your test class file:

<?php

namespace MyVendor\MyBundle\Tests\Units\Entity;

require_once 'path/to/MyVendor/Entity/MyEntity.php'

class MyEntity 
{
    //...   
}
mageekguy commented 10 years ago

@flip111:

Atoum try to define automatically the tested class name to improve the user experience. For example, the asserter $this->object($foo->doesSomething())->isTestedInstance rely on this, and code coverage and many other cool features too.

But it's a default mechanism and you can override it, like many (every?) other things in atoum which have a default behavior.

So, you have currently two solutions available to do that.

Firstly, you can use in the __construct of your test class, after the call to the parent constructor, the setTestedClassName method:

public function __construct(adapter $adapter = null, annotations\extractor $annotationExtractor = null, asserter\generator $asserterGenerator = null, test\assertion\manager $assertionManager = null, \closure $reflectionClassFactory = null)
{
   parent::__construct($adapter, $annotationExtractor, $asserterGenerator, $assertionManager, $reflectionClassFactory);
   $this->setTestedClassName('MyVendor\Entity\MyEntity);
}

And secondly, you can overload the static getTestedClassNameFromTestClass method if you can define a generic algorithm to define all tested class name.

And at least, it's certainly possible to define the tested class name with an annotation, so if you want that, just do the PR, me and @jubianchi will be happy to help you in this task.

Best regards, Fred.

flip111 commented 10 years ago

@jubianchi

But i don't think it's the job of the autoloader to find the corresponding class of the test !

So in steps i think it's like this:

  1. atoum bootstrap instructs autoloader to load test classes
  2. autoloader finds files for classes
  3. atoum handles test classes
  4. atoum instructs autoloader to find class under test <-- this is the step i'm talking about
  5. autoloader finds file of class under test

@mageekguy yes thank you, that was what i was looking for !

jubianchi commented 10 years ago

@flip111 sorry I misread part of what you wrote. What I understood was that your tested class had a namesapce not matching its path which would have been an autoloader issue.

@mageekguy answer is right then.

I still have a question: what is the point of adding the test in a bundle/module/library when the class it tests is not part of this bundle/module/library ?

To me, the test has to follow what it tests, especially in unit context.

flip111 commented 10 years ago

Fair point. To be honest i don't know right right now because the issue is 2 months ago and i can't view the code at the moment. I'll be sure to post back when i figured out the actual use case for it.