Как зайти в Даркнет?!
25th January, 01:11
6
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
894
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
914
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Выполните PHPUnit тестов в определенном порядке
Есть ли способ заставить тесты внутри TestCase выполняться в определенном порядке? Например, я хочу отделить жизненный цикл объекта от создания для использования до уничтожения, но мне нужно убедиться, что объект настроен первым, прежде чем я выполню другие тесты.
PHPUnit поддерживает тестовые зависимости через аннотацию @depends .
Вот пример из документации, где тесты будут выполняться в порядке, удовлетворяющем зависимостям, причем каждый зависимый тест передает аргумент следующему:
class StackTest extends PHPUnit_Framework_TestCase
{
public function testEmpty()
{
$stack = array();
$this->assertEmpty($stack);
return $stack;
}
/**
* @depends testEmpty
*/
public function testPush(array $stack)
{
array_push($stack, 'foo');
$this->assertEquals('foo', $stack[count($stack)-1]);
$this->assertNotEmpty($stack);
return $stack;
}
/**
* @depends testPush
*/
public function testPop(array $stack)
{
$this->assertEquals('foo', array_pop($stack));
$this->assertEmpty($stack);
}
}
Однако важно отметить, что тесты с неразрешенными зависимостями не будут выполняться (желательно, так как это быстро привлечет внимание к неудачному тесту). Поэтому при использовании зависимостей важно обращать на них самое пристальное внимание.
Возможно, в ваших тестах есть проблема с дизайном.
Обычно каждый тест не должен зависеть от каких-либо других тестов, поэтому они могут выполняться в любом порядке.
Каждый тест должен создавать экземпляры и уничтожать все, что ему нужно выполнить, что было бы идеальным подходом, вы никогда не должны делиться объектами и состояниями между тестами.
Не могли бы Вы уточнить, зачем вам нужен один и тот же объект для N тестов?
Правильный ответ на этот вопрос-это правильный конфигурационный файл для тестов. У меня была та же проблема, и я исправил ее, создав testsuite с необходимым порядком тестовых файлов:
phpunit.xml:
<phpunit
colors="true"
bootstrap="./tests/bootstrap.php"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
strict="true"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
stopOnRisky="false"
>
<testsuites>
<testsuite name="Your tests">
<file>file1</file> //this will be run before file2
<file>file2</file> //this depends on file1
</testsuite>
</testsuites>
</phpunit>
На мой взгляд, возьмем следующий сценарий, где мне нужно протестировать создание и уничтожение конкретного ресурса.
Изначально у меня было два метода: a. testCreateResource и b. testDestroyResource
а. testCreateResource
<?php
$app->createResource('resource');
$this->assertTrue($app->hasResource('resource'));
?>
б. testDestroyResource
<?php
$app->destroyResource('resource');
$this->assertFalse($app->hasResource('resource'));
?>
Я думаю, что это плохая идея, так как testDestroyResource зависит от testCreateResource. И лучшей практикой было бы это сделать
а. testCreateResource
<?php
$app->createResource('resource');
$this->assertTrue($app->hasResource('resource'));
$app->deleteResource('resource');
?>
б. testDestroyResource
<?php
$app->createResource('resource');
$app->destroyResource('resource');
$this->assertFalse($app->hasResource('resource'));
?>
Альтернативное решение: Используйте статические(!) функции в ваших тестах для создания повторно используемых элементов. Например (я использую selenium IDE для записи тестов и phpunit-selenium (github) для запуска теста внутри браузера)
class LoginTest extends SeleniumClearTestCase
{
public function testAdminLogin()
{
self::adminLogin($this);
}
public function testLogout()
{
self::adminLogin($this);
self::logout($this);
}
public static function adminLogin($t)
{
self::login($t, 'john.smith@gmail.com', 'pAs$w0rd');
$t->assertEquals('John Smith', $t->getText('css=span.hidden-xs'));
}
// @source LoginTest.se
public static function login($t, $login, $pass)
{
$t->open('/');
$t->click("xpath=(//a[contains(text(),'Log In')])[2]");
$t->waitForPageToLoad('30000');
$t->type('name=email', $login);
$t->type('name=password', $pass);
$t->click("//button[@type='submit']");
$t->waitForPageToLoad('30000');
}
// @source LogoutTest.se
public static function logout($t)
{
$t->click('css=span.hidden-xs');
$t->click('link=Logout');
$t->waitForPageToLoad('30000');
$t->assertEquals('PANEL', $t->getText("xpath=(//a[contains(text(),'Panel')])[2]"));
}
}
Хорошо, а теперь я могу использовать эти многоразовые элементы в другом тесте :) например:
class ChangeBlogTitleTest extends SeleniumClearTestCase
{
public function testAddBlogTitle()
{
self::addBlogTitle($this,'I like my boobies');
self::cleanAddBlogTitle();
}
public static function addBlogTitle($t,$title) {
LoginTest::adminLogin($t);
$t->click('link=ChangeTitle');
...
$t->type('name=blog-title', $title);
LoginTest::logout($t);
LoginTest::login($t, 'paris@gmail.com','hilton');
$t->screenshot(); // take some photos :)
$t->assertEquals($title, $t->getText('...'));
}
public static function cleanAddBlogTitle() {
$lastTitle = BlogTitlesHistory::orderBy('id')->first();
$lastTitle->delete();
}
- Таким образом, вы можете построить иерархию ваших тестов.
- Вы можете также сохранить свойство, что каждый тестовый случай полностью отделен от другого (если вы очистите DB после каждого теста).
- И самое главное, если, например, способ входа в систему изменится в будущем, вы только измените класс LoginTest, и вам не нужна корректная часть входа в другие тесты (они должны работать после обновления LoginTest) :)
Когда я запускаю тестовый скрипт clean up db ad The begining. Выше я использую свой класс SeleniumClearTestCase (я делаю screenshot() и другие приятные функции там) это расширение MigrationToSelenium2 (от github, чтобы перенести записанные тесты в firefox с помощью seleniumIDE + FF plugin "Selenium IDE: PHP Formatters"), которое является расширением моего класса LaravelTestCase (это копия Illuminate\Foundation\Testing\TestCase, но не расширяет PHPUnit_Framework_TestCase), который настраивает laravel, чтобы иметь доступ к eloquent, когда мы хотим очистить DB в конце теста), который является расширением PHPUnit_Extensions_Selenium2Testcase. Для настройки laravel eloquent у меня есть также в SeleniumClearTestCase функция createApplication (которая вызывается в setUp , и я беру эту функцию из laral test/TestCase)
Там действительно есть проблема с вашими тестами, если они должны выполняться в определенном порядке. Каждый тест должен быть полностью независим от других: он помогает вам с локализацией дефектов и позволяет получить повторяемые (и, следовательно, отлаживаемые) результаты.
Проверьте этот сайт для получения целого груза идей / информации, о том, как факторизовать свои тесты таким образом, чтобы избежать подобных проблем.