I'm trying to build Yii2 app through unit testing and i have some questions about it.
class UsersTest extends \Codeception\TestCase\Test
{
/**
* #var \UnitTester
*/
protected $users;
protected function _before()
{
$this->users = new \app\models\Users;
}
protected function _after()
{
}
// tests
public function testGeId()
{
}
}
When i try to run this test class i have fatal error message that Users class not found. What cause of the problem and how to solve it?
There is readme file in Yii2 tests folder which tell us to setup yii2-faker and yii2_basic_tests database. What are these two things and why i should to use them?
Thank you.
It was need to create application instance in tests/_bootstrap.php. It must be following code in that file:
require('/../vendor/autoload.php');
require('/../vendor/yiisoft/yii2/Yii.php');
$config = require('config/web.php');
(new yii\web\Application($config));
Possibly you
settings:
bootstrap: _bootstrap.php
in codeception.yml is wrong? This file include vendor/autoload.php and class names resolved
defined the auto loader in the phpunit xml configuration file
<?xml version="1.0" encoding="utf-8" ?>
<phpunit bootstrap="./vendor/autoload.php">
<testsuites>
<testsuite name="The project's test suite">
<directory>./tests</directory>
</testsuite>
</testsuites>
</phpunit>
Related
I'm trying to create a dynamic product discount using values from a webservice.
I've searched some guides on the internet about this matter and I found that I needed to use checkout_cart_product_add_after and checkout_cart_update_items_after.
However, I followed some guides. Created my own module (which is visible in Magento back office: Configuration > Advanced > Modules) and a observer for this module. I didn't create anything more but it's not working. Since I can see the module in that menu, I believe the problem is on the observer/event call.
Here is the config.xml (which is inside app\code\local\namespace\MyModule\etc) for my module:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<namespace_MyModule>
<version>0.1.0</version>
</namespace_MyModule>
</modules>
<global>
<events>
<checkout_cart_product_add_after>
<observers>
<namespace_MyModule_Discount>
<class>MyModule/Observer</class>
<method>MyModulePriceChange</method>
</namespace_MyModule_Discount>
</observers>
</checkout_cart_product_add_after>
</events>
</global>
</config>
And this is my Observer (which is inside app\code\local\namespace\MyModule\Model) for my module:
<?php
class namespace_MyModule_Model_Observer
{
public function MyModulePriceChange(Varien_Event_Observer $obs)
{
// Get the quote item
$item = $obs->getQuoteItem();
// Ensure we have the parent item, if it has one
$item = ( $item->getParentItem() ? $item->getParentItem() : $item );
// Load the custom price
$price = $this->_getPriceByItem($item);
// Set the custom price
$item->setCustomPrice($price);
$item->setOriginalCustomPrice($price);
// Enable super mode on the product.
$item->getProduct()->setIsSuperMode(true);
}
protected function _getPriceByItem(Mage_Sales_Model_Quote_Item $item)
{
$price = 4;
//use $item to determine your custom price.
return $price;
}
}
?>
Also, is it possible do call soap client to use a webservice inside a observer?
I hope my question is clear, thank you in advance for helping.
I see some issues with your config.xml. First of all, use capitalized both company name and module name. namespace_MyModule will become your namespace.
You have to declare models under global section like this:
<models>
<mycompany_mymodule>
<class>Mycompany_Mymodule_Model</class>
</mycompany_mymodule>
</models>
This will tell magento you want to use mycompany_mymodule for models in your module, and class name of each module will start with Mycompany_Mymodule_Model.
Where Mycompany and Mymodule are respective to folders of your module: app/code/local/Mycompany/Mymodule.
The modules section of config.xml should also have this namespace (Mycompany_Mymodule), matching name of your file app/etc/modules and folder structure in app/code/local.
The observers then become the following (I added type, and changed class):
<observers>
<namespace_MyModule_Discount>
<type>singleton</type>
<class>mycompany_mymodule/Observer</class>
<method>MyModulePriceChange</method>
</namespace_MyModule_Discount>
</observers>
Then try to test your observer method by adding there some code like die("message").
You haven't declared the models tag in the config.xml file.
An observer is a model after all and magento will not know where to find it (that MyModule/Observer you reference). Below it's an example of declaring models tag:
<models>
<MyModule>
<class>Namespace_Modulename_Model</class>
</MyModule>
</models>
Yes, you can do soap api calls inside observer.
I have prepared a testng.xml file where I put number of test classes to run, for example:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<!-- REMOTE PROJECT -->
<suite name="Suite1" preserve-order="true">
<test name="Test1">
<parameter name="browsers" value="Chrome">
</parameter>
<classes>
<class name="com.project.live.Class1" />
<class name="com.project.live.Class2" />
<class name="com.project.live.Class3" />
...
...
...
<class name="com.project.live.Class...Nth" />
</classes>
</test>
<!-- Test -->
</suite> <!-- Suite -->
There are test cases in these classes with #Test Annotation, I want to run selected test cases only i.e. I will skip some tests of these classes.
1. One way to do this is put #Ignore Annotation and remove #Test Annotation from tests which I don't want to run (but that's lengthy work, very time consuming)
2. Another way is to use groupsbut again it is lengthy to select tests and put them in groups.
Query:Is there any optimal way to achieve this, may be some customized config file?
One way can be to use Iannotationtransformer.
Put another file which contains the list of cases to exclude (or include whichever list is shorter). Implement the transform method to check whether the current method falls in this exclude list, if yes, then set the enabled property to false for the annotation and it would be excluded.
Could you try IMethodInterceptor for this purpose?
Configure your test class with a listener implementing IMethodInterceptor and decide the tests to be run dynamically
A sample listener below.
public class MyTestListener implements IMethodInterceptor {
#Override
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
List<IMethodInstance> methodlist = new ArrayList<IMethodInstance>();
// Read these flags from somewhere, system var / test context / file or
// where ever
Boolean shouldRunTest1 = Boolean.valueOf(context.getAttribute("SHOULD_RUN_TEST1")
.toString());
Boolean shouldRunTest2 = Boolean.valueOf(context.getAttribute("SHOULD_RUN_TEST2")
.toString());
for (IMethodInstance iMethodInstance : methods) {
// decide based on method name / group / priority / description or
// what ever
String methodName = iMethodInstance.getMethod().getMethodName();
if (iMethodInstance.getMethod().isTest()) {
if (shouldRunTest1 && methodName.equals("testCase1")) {
methodlist.add(iMethodInstance);
} else if (shouldRunTest2 && methodName.equals("testCase2")) {
methodlist.add(iMethodInstance);
}
}
}
// Here we return the test cases to be run
return methodlist;
}
see the below example ,when u wanted to run only "sanity3" ,you can comment the other methods(sanity0 ....sanity2) and run using xml file (right click and Run as ->testng)
Eg:
<run>
<!-- <include name="Sanity0"/>
<include name="Sanity1"/>
<include name="Sanity2"/> -->
<include name="Sanity3"/>
Similarly to How can I make my JUnit tests run in random order? , I'd like TestNG to run my tests in random order, so unintended dependencies cannot creep in.
The TestNG manual states:
By default, TestNG will run the tests found in your testng.xml file in
a random order.
However, I created a small test project, with a simple testng.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="My suite">
<test name="Simple test">
<packages>
<package name="testngtests"></package>
</packages>
</test>
</suite>
The package testngtests contains two test classes (MyTest1, MyTest2), and these contain a few empty methods like this:
#Test
public void testOne(){
}
The test mehods are all empty, and only differ by name.
When I run them (using the Eclipse TestNG runner, or on the command line), the tests consistenly run in the same order (namely sorted alphabetically, first by class and then by method name).
So is the documentation wrong?
Or does "in random order" simply mean "there is no guaranteed order"? Then how can I make TestNG actively randomize test order?
Yes, 'random' should really be 'non predictable'.
If you want true randomization, look up IMethodInterceptor, where TestNG will give you an opportunity to change the ordering to anything you like.
To expand on Cedric Beust's answer, here's my code for doing this, with some help from this example from GitHub:
import org.testng.IMethodInstance;
import org.testng.IMethodInterceptor;
import org.testng.ITestContext;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class TestOrderRandomizer implements IMethodInterceptor {
#Override
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
long seed = System.nanoTime();
System.out.println(String.format("Randomizing order of tests with seed: %s", seed));
Collections.shuffle(methods, new Random(seed));
return methods;
}
}
And to use it, add this before your test class:
import org.testng.annotations.Listeners;
#Listeners(TestOrderRandomizer.class)
public class TesterClass {
...
Printing the seed allows to reproduce a run-order by planting the same seed again.
I have been looking for a tutorial to help me integrate PHPUnit with CakePHP. Looking to use Selenium tests too so prefer PHPUnit.
I have been trying to follow the tutorial on http://cakebaker.42dh.com/2006/03/22/selenium/ but cant seem to get it work. Any good tutorials out there?
Thanks!
It's relatively easy. I use cake 1.3 from composer installation. This is how my composer.json looks like:
{
"config": {
"vendor-dir": "vendors/composer"
},
"require": {
"phpunit/phpunit": "3.7.*",
"cakephp/cakephp-1.3": "1.3",
},
"repositories": [
{
"type": "package",
"package": {
"name": "cakephp/cakephp-1.3",
"version": "1.3",
"source": {
"url": "https://github.com/cakephp/cakephp.git",
"type": "git",
"reference": "1.3"
}
}
}
]
}
Then the phpunit bootstrap.php file in tests directory:
<?php
include('../vendors/composer/autoload.php');
include('../webroot/index.php');
This is phpunit.xml form the same dir:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="bootstrap.php"
backupStaticAttributes="false"
cacheTokens="false"
colors="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
forceCoversAnnotation="false"
mapTestClassNameToCoveredClassName="false"
printerClass="PHPUnit_TextUI_ResultPrinter"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader"
strict="false"
verbose="false"
>
<testsuites>
<testsuite name="AllTests">
<directory>.</directory>
</testsuite>
</testsuites>
<filter>
<blacklist>
<directory suffix=".php"></directory>
<file></file>
<exclude>
<directory suffix=".php"></directory>
<file></file>
</exclude>
</blacklist>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php"></directory>
<file></file>
<exclude>
<directory suffix=".php"></directory>
<file></file>
</exclude>
</whitelist>
</filter>
</phpunit>
Don't forget to load your application classes in test setup. You can do it cakephp way. For example if your controller is named calendar your calendarTest.php may look like:
<?php
/**
* Class ComponentsCommonTest
* #property calendarController $calendarController
*/
class CalendarTest extends PHPUnit_Framework_TestCase
{
/**
* #var calendarController $calendarController
*/
private $calendarController;
function setUp()
{
App::import('Core', array('View', 'Controller', 'Model', 'Router'));
App::import('Controller', 'Calendar');
$this->calendarController =& new CalendarController();
$this->calendarController->constructClasses();
$this->calendarController->layout = null;
}
}
The same for models, vendor classes and so on. Works great for me.
Unfortunately CakePHP isn't designed to work together with PHPUnit. CakePHP has switched to using SimpleTest and you'll have one of two choices, refactor your tests to work with SimpleTest or modify the core to use PHPUnit.
However it should be stated that Mark Story has stated that CakePHP 2.0 will use PHPUnit for it's testing framework, so if you can aford to wait till then that may wind up being the best option.
CakePHP 1.3 Book on Testing
I am having trouble getting my filters/validators to work correctly on my form, so I want to create a Unit test to verify that the data I am submitting to my form is being filtered and validated correctly.
I started by auto-generating a PHPUnit test in Zend Studio, which gives me this:
<?php
require_once 'PHPUnit/Framework/TestCase.php';
/**
* Form_Event test case.
*/
class Form_EventTest extends PHPUnit_Framework_TestCase
{
/**
* #var Form_Event
*/
private $Form_Event;
/**
* Prepares the environment before running a test.
*/
protected function setUp ()
{
parent::setUp();
// TODO Auto-generated Form_EventTest::setUp()
$this->Form_Event = new Form_Event(/* parameters */);
}
/**
* Cleans up the environment after running a test.
*/
protected function tearDown ()
{
// TODO Auto-generated Form_EventTest::tearDown()
$this->Form_Event = null;
parent::tearDown();
}
/**
* Constructs the test case.
*/
public function __construct ()
{ // TODO Auto-generated constructor
}
/**
* Tests Form_Event->init()
*/
public function testInit ()
{
// TODO Auto-generated Form_EventTest->testInit()
$this->markTestIncomplete(
"init test not implemented");
$this->Form_Event->init(/* parameters */);
}
/**
* Tests Form_Event->getFormattedMessages()
*/
public function testGetFormattedMessages ()
{
// TODO Auto-generated Form_EventTest->testGetFormattedMessages()
$this->markTestIncomplete(
"getFormattedMessages test not implemented");
$this->Form_Event->getFormattedMessages(/* parameters */);
}
}
so then I open up terminal, navigate to the directory, and try to run the test:
$ cd my_app/tests/unit/application/forms
$ phpunit EventTest.php
Fatal error: Class 'Form_Event' not found in .../tests/unit/application/forms/EventTest.php on line 19
So then I add a require_once at the top to include my Form class and try it again. Now it says it can't find another class. I include that one and try it again. Then it says it can't find another class, and another class, and so on. I have all of these dependencies on all these other Zend_Form classes. What should I do? How should I go about testing my Form to make sure my Validators and Filters are being attached correctly, and that it's doing what I expect it to do. Or am I thinking about this the wrong way?
you have to use your Zend Framework Application Configuration altough for your Unittests. If you work with the "XML" Config of PHPUnit add an Bootstrap File wich runs before the tests are executed.
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="TestConfig.php">
<testsuite name="XY">
<directory>./</directory>
</testsuite>
</phpunit>
In your TestConfig.php setup the AutoLoader and other needed ressources, or use the config.ini from your Application like in my example.
$includeConfig = parse_ini_file(TEST_PATH . '/config/config.ini', true);
set_include_path(
implode(PATH_SEPARATOR, $includeConfig['includes'])
. PATH_SEPARATOR
. TEST_PATH . PATH_SEPARATOR
. get_include_path()
);
unset($includeConfig);
require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('App_');
If you need more hints check out this Tutorial on Zend Framework with PHPUNIT
PHPUnit + Zend Framework