How write tests. Can you look at my first testCase?

Notice: This thread is very old.
Čamo
Member | 786
+
0
-

Today I wrote my first test and it works well. I would like to know how to improve it or what is wrong.
Every comment is appreciated.
So this is the bootstrap.php

<?php

require __DIR__ . '/../vendor/autoload.php';

Tester\Environment::setup();

$configurator = new Nette\Configurator;
$configurator->setDebugMode(FALSE);
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
	->addDirectory(__DIR__ . '/../app')
	->register();

$configurator->addConfig(__DIR__ . '/../app/config/config.neon');
$configurator->addConfig(__DIR__ . '/../app/config/config.local.neon');

return $configurator->createContainer();

php.ini

extension = /PHP56/ext/php_pdo_mysql.dll
extension = /PHP56/ext/php_pdo_pgsql.dll

memory_limit = 512M

BaseTest

<?php


namespace Test;


use Nette;
use Tester;


abstract class BaseTest extends Tester\TestCase
{

	protected $container;

	protected $presenter;


	public function __construct( Nette\DI\Container $container )
	{
		$this->container = $container;
	}


	protected function getPresenter( $name, $canonicalize = FALSE )
	{
		$presenter = $this->container->getByType( 'Nette\Application\IPresenterFactory' )->createPresenter( $name );
		$presenter->autoCanonicalize = $canonicalize;

		return $presenter;
	}

}

ArticlesPresenterTest

<?php

/**
 * @testCase
 */

namespace Test;


$container = require __DIR__ . '/../bootstrap.php';
require_once( __DIR__ . '/../BaseTest.php' );


use App;
use Nette;
use Kdyby;
use Tester\Assert;


class ArticlesPresenterTest extends BaseTest
{

	public function setUp()
	{
		$this->presenter = $this->getPresenter( 'Articles' );
	}


	public function tearDown()
	{
		# Úklid
	}


	/**
	 * @desc This tests mainly injected services and components from BasePresenter and ArticlesPresenter.
	 */
	public function testBaseDependencies()
	{
		$category = $this->presenter->categories->findOneBy( [ 'id !=' => NULL ] );
		$request = new Nette\Application\Request( 'Articles', 'GET', [
			'action' => 'show',
			'title'  => $category->getSlug(),
		] );

		Assert::true( $this->presenter->em instanceof Kdyby\Doctrine\EntityManager );
		Assert::true( $this->presenter->categories instanceof App\Model\Categories );
		Assert::true( $this->presenter['menu'] instanceof App\Controls\Menu );
		Assert::true( $this->presenter['breadcrumbs'] instanceof App\Controls\Breadcrumbs );

		$response = $this->presenter->run( $request );
		Assert::true( $response instanceof Nette\Application\Responses\TextResponse );

		$template = $response->getSource();
		Assert::true( $template instanceof Nette\Application\UI\ITemplate );

	}


	/**
	 * @desc This tests RenderShow action for some category.
	 * @param $category
	 */
	public function testRenderShow( $category = NULL )
	{
		$category = $this->presenter->categories->findOneBy( [ 'id !=' => NULL ] );
		$request = new Nette\Application\Request( ':Articles', 'GET', [
			'action' => 'show',
			'title'  => $category->getSlug(),
		] );

		$response = $this->presenter->run( $request );
		$template = $response->getSource();

		Assert::true( $template->articles instanceof Kdyby\Doctrine\ResultSet );
	}


	/**
	 * @desc This expects exception with code 404 because of title param which does not exist.
	 * @param string $title
	 */
	public function testRenderShow2( $title = 'With title parameter which does not exist.' )
	{
		$presenter = $this->presenter;
		$request = new Nette\Application\Request( ':Articles', 'GET', array(
			'action' => 'show',
			'title'  => $title,
		) );

		Assert::exception( function () use ( $presenter, $request )
		{
			$this->presenter->run( $request );
		}, 'Nette\Application\BadRequestException', NULL, 404 );

	}


	/**
	 * @desc This test RenderShow for one article.
	 * @param string $title
	 */
	public function testRenderShow3( $title = NULL )
	{
		$title = $this->presenter->articles->findOneBy( [ 'id !=' => NULL ] );
		$request = new Nette\Application\Request( ':Articles', 'GET', array(
			'action' => 'show',
			'title'  => $title->getUrlTitle(),
		) );

		$response = $this->presenter->run( $request );
		$template = $response->getSource();

		Assert::true( $template->article instanceof App\Model\Entity\Article );

	}

}

# Spuštění testovacích metod
( new ArticlesPresenterTest( $container ) )->run();

Last edited by Čamo (2016-03-18 23:09)

fmasa
Member | 2
+
0
-

What exactely is the point of the test.

First test (testBaseDependencies) is IMO pointless, because all you're testing is DI autowiring.

The other tests seem to be some kind of integration test. There are several improvements that can/should be made.

First of all:
test (case) should contain three phases:

1. “Given”:
Prepare/mock/stub dependencies and create tested object. INSERT necessary data into database, prepare filesystem or whatever your dependencies are.
2. “When”
Perform tested action (invoke presenter action in your case). That's the easy one :)
3. “Then”
Check whether result matches your expectations.

Where are the articles created? I don't see it anywhere in that test case or bootstrap. Does your test depend on live database? What if you want to run two tests – “show” action and “delete” action?

Čamo
Member | 786
+
0
-

fmasa
Yes, I do it on live database. I don't know how and on what level to create parallel database. Also what is necessary to set up if I want to run parallel DB. Thats the reason why there are no delete/create test. I am little confused about how it works.

If you have some useful links past it here please.
I found these
http://blog.janmarek.net/…m-presenteru
http://zlml.cz/…teru-v-nette
http://zlml.cz/…plne-kazdeho

Last edited by Čamo (2016-03-22 22:40)