Этот пакет устарел, вместо него проверьте Infection.
Humbug — это среда мутационного тестирования PHP. В настоящее время он находится в разработке, и, хотя на самом деле он работает довольно хорошо, у него будут острые углы, над которыми усердно работает команда миньонов. Если он выпадет за ворота, вас предупредили ;).
$ git remote set-url upstream https://github.com/humbug/humbug.git
Замените upstream
именем удаленного устройства, которое вы используете локально; обычно используется upstream
, но вы можете использовать что-то другое. Вы также можете использовать другой URL-адрес (например, [email protected]:mockery/mockery.git). Запустите git remote -v
чтобы увидеть, что вы на самом деле используете.
Оглавление
Короче говоря, мутационное тестирование — это возможность дать вашим юнит-тестам возможность оправдать свои деньги. Он включает в себя внесение небольших дефектов в исходный код и последующую проверку того, заметили ли модульные тесты. Если да, то ваши модульные тесты «уничтожили» мутацию. В противном случае мутация ускользнула от обнаружения. Поскольку модульные тесты предназначены для предотвращения регрессий, было бы плохо, если бы реальная регрессия прошла незамеченной!
В то время как покрытие кода может сказать вам, какой код выполняют ваши тесты, мутационное тестирование предназначено для того, чтобы помочь вам оценить, насколько хорошо на самом деле работают ваши модульные тесты и где их можно улучшить.
Подробнее о том, почему стоит проводить мутационное тестирование, я написал: Ложь, наглая ложь и покрытие кода: на пути к мутационному тестированию.
Humbug — это проект с открытым исходным кодом, который приветствует запросы на включение и решение проблем от всех. Прежде чем открывать запросы на включение, прочтите наше краткое руководство по участию.
Вы можете клонировать и установить зависимости Humbug с помощью Composer:
git clone https://github.com/humbug/humbug.git
cd humbug
/path/to/composer.phar install
Команда обмана теперь находится в bin/humbug.
Если вы не хотите напрямую отслеживать главную ветку, вы можете установить Humbug phar следующим образом:
wget https://padraic.github.io/humbug/downloads/humbug.phar
wget https://padraic.github.io/humbug/downloads/humbug.phar.pubkey
# If you wish to make humbug.phar directly executable
chmod +x humbug.phar
В Windows вы можете просто загрузить с помощью браузера или из Powershell v3, используя следующие команды, где wget
— это псевдоним Invoke-WebRequest
:
wget https://padraic.github.io/humbug/downloads/humbug.phar -OutFile humbug.phar
wget https://padraic.github.io/humbug/downloads/humbug.phar.pubkey -OutFile humbug.phar.pubkey
Если вы застряли на Powershell v2:
$client = new-object System.Net.WebClient
$client .DownloadFile( " https://padraic.github.io/humbug/downloads/humbug.phar " , " humbug.phar " )
$client .DownloadFile( " https://padraic.github.io/humbug/downloads/humbug.phar.pubkey " , " humbug.phar.pubkey " )
Phar подписывается закрытым ключом openssl. Чтобы использовать его, вам нужно, чтобы файл pubkey постоянно хранился рядом с файлом phar. Например, если вы переименуете humbug.phar
в humbug
, то также переименуйте ключ с humbug.phar.pubkey
в humbug.pubkey
.
Релизы phar в настоящее время выполняются вручную, поэтому они не будут обновляться с той же частотой, что и git master. Чтобы обновить текущий Phar, просто запустите:
./humbug.phar self-update
Примечание. Использование phar означает, что исправления могут занять больше времени, чтобы дойти до вашей версии, но есть больше уверенности в том, что вы получите стабильную версию для разработки. Открытый ключ загружается только один раз. Он повторно используется при самостоятельном обновлении для проверки будущих выпусков phar.
Как только выпуски начнут приближаться к стабильной версии, появятся альфа-версия, бета-версия, RC и финальная версия. Ваш phar-файл трека разработки будет автоматически обновляться до тех пор, пока не достигнет стабильной версии. Если вы хотите продолжить отслеживание phars уровня разработки, вам нужно будет указать это с помощью одного из флагов стабильности:
./humbug.phar self-update --dev
Если у вас возникли проблемы с самообновлением и неожиданные ошибки openssl
или SSL, убедитесь, что вы включили расширение openssl
. В Windows вы можете сделать это, добавив или раскомментировав следующую строку в файле php.ini
для PHP в командной строке (если она отличается от файла для вашего http-сервера):
extension=php_openssl.dll
Некоторые другие ошибки SSL могут возникнуть из-за отсутствия сертификатов. Вы можете исправить это, найдя их местоположение в своей системе (например, C:/xampp/php/ext/cacert.pem
) или, альтернативно, загрузив копию с http://curl.haxx.se/ca/cacert.pem. Затем убедитесь, что следующий параметр правильно указывает на этот файл:
openssl.cafile=C:/path/to/cacert.pem
Поскольку зависимости Humbug привязаны к последним версиям, добавление Humbug в композитор.json может привести к конфликтам. В таких случаях предпочтительны два вышеуказанных метода установки. Однако вы можете установить его глобально, как и любой другой инструмент общего назначения:
composer global require ' humbug/humbug=~1.0@dev '
И если вы еще этого не сделали... добавьте это в ~/.bash_profile
(или ~/.bashrc
):
export PATH= ~ /.composer/vendor/bin: $PATH
Humbug в настоящее время работает на PHP 5.4 или выше.
Humbug все еще находится в стадии разработки, поэтому, повторюсь, остерегайтесь острых углов.
Чтобы настроить обман в вашем проекте, вы можете запустить:
humbug configure
Этот инструмент задаст несколько вопросов, необходимых для создания файла конфигурации Humbug ( humbug.json.dist
).
В базовом каталоге вашего проекта создайте файл humbug.json.dist
:
{
"timeout" : 10 ,
"source" : {
"directories" : [
"src"
]
} ,
"logs" : {
"text" : "humbuglog.txt" ,
"json" : "humbuglog.json"
}
}
Вы можете зафиксировать humbug.json.dist
в своей VCS и переопределить его локально с помощью файла humbug.json
.
Отредактируйте по мере необходимости. Если вы не определите хотя бы один журнал, подробная информация о сбежавших мутантах не будет доступна. Текстовый журнал удобен для чтения человеком. Если исходные файлы существуют в базовом каталоге или файлы в исходных каталогах должны быть исключены, вы можете добавить шаблоны исключения (здесь один для файлов в базовом каталоге, где исключены каталоги Composer Vendor и Tests):
{
"timeout" : 10 ,
"source" : {
"directories" : [
"."
] ,
"excludes" : [
"vendor" ,
"Tests"
]
} ,
"logs" : {
"text" : "humbuglog.txt"
}
}
Если из базового каталога вашего проекта вам необходимо запустить тесты из другого каталога, вы также можете сигнализировать об этом. Вам не нужно запускать Humbug из любого каталога, кроме базового каталога вашего проекта.
{
"chdir" : "tests" ,
"timeout" : 10 ,
"source" : {
"directories" : [
"src"
] ,
}
}
Убедитесь, что все ваши тесты находятся в состоянии «пройдено» (допускаются неполные и пропущенные тесты). Humbug прекратит работу, если какой-либо из ваших тестов не пройден.
Волшебная команда в базовом каталоге вашего проекта (с использованием загрузки PHAR):
./humbug.phar
или если вы только что клонировали Humbug:
../humbug/bin/humbug
или если вы добавили Humbug в качестве зависимости композитора в свой проект:
./vendor/bin/humbug
Вместо php с расширением xdebug вы также можете запустить Humbug через phpdbg:
phpdbg -qrr humbug.phar
Если все прошло хорошо, вы получите что-то похожее на:
_ _ _
| || |_ _ _ __ | |__ _ _ __ _
| __ | || | ' | '_ || / _` |
|_||_|_,_|_|_|_|_.__/_,___, |
|___/
Humbug version 1.0-dev
Humbug running test suite to generate logs and code coverage data...
361 [==========================================================] 28 secs
Humbug has completed the initial test run successfully.
Tests: 361 Line Coverage: 64.86%
Humbug is analysing source files...
Mutation Testing is commencing on 78 files...
(.: killed, M: escaped, S: uncovered, E: fatal error, T: timed out)
.....M.M..EMMMMMSSSSMMMMMSMMMMMSSSE.ESSSSSSSSSSSSSSSSSM..M.. | 60 ( 7/78)
...MM.ES..SSSSSSSSSS...MMM.MEMME.SSSS.............SSMMSSSSM. | 120 (12/78)
M.M.M...TT.M...T.MM....S.....SSS..M..SMMSM...........M...... | 180 (17/78)
MM...M...ESSSEM..MMM.M.MM...SSS.SS.M.SMMMMMMM..SMMMMS....... | 240 (24/78)
.........SMMMSMMMM.MM..M.SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS | 300 (26/78)
SSSSSSSSM..E....S......SS......M.SS..S..M...SSSSSSSS....MMM. | 360 (37/78)
.M....MM..SM..S..SSSSSSSS.EM.S.E.M............M.....M.SM.M.M | 420 (45/78)
..M....MMS...MMSSS................M.....EME....SEMS...SSSSSS | 480 (52/78)
SSSSS.EMSSSSM..M.MMMM...SSE.....MMM.M..MM..MSSSSSSSSSSSSSSSS | 540 (60/78)
SSS....SSSSSSSSMM.SSS..........S..M..MSSMS.SSSSSSSSSSSSSSSSS | 600 (68/78)
......E...M..........SM.....M..MMMMM.MMMMMSSSSSSSM.SS
653 mutations were generated:
284 mutants were killed
218 mutants were not covered by tests
131 covered mutants were not detected
17 fatal errors were encountered
3 time outs were encountered
Metrics:
Mutation Score Indicator (MSI): 47%
Mutation Code Coverage: 67%
Covered Code MSI: 70%
Remember that some mutants will inevitably be harmless (i.e. false positives).
Humbug results are being logged as JSON to: log.json
Humbug results are being logged as TEXT to: log.txt
Чтобы объяснить, возможно, загадочный результат выполнения:
Убийства, ошибки и тайм-ауты считаются обнаруженными мутациями. Мы сообщаем об ошибках в журналах на тот случай, если Humbug сам обнаружит внутреннюю ошибку, то есть ошибку, о которой следует сообщить здесь как о проблеме!
В сводных результатах примера указано несколько оценок показателей:
Если вы исследуете эти показатели, вы увидите, что выдающаяся проблема заключается в том, что MSI, равный 47%, на 18 пунктов ниже заявленного показателя покрытия кода, составляющего 65%. Эти модульные тесты гораздо менее эффективны, чем можно было бы обнаружить только с помощью Code Coverage.
Интерпретация этих результатов требует некоторого контекста. В журналах будут перечислены все необнаруженные мутации как различия с исходным исходным кодом. Их изучение даст дальнейшее понимание того, какие конкретные мутации остались незамеченными.
У Humbug есть несколько примечательных параметров командной строки, кроме тех, которые обычно связаны с любым консольным приложением Symfony.
Вы можете вручную установить порог тайм-аута для любого отдельного теста:
humbug --timeout=10
Если вас интересует только изменение подмножества ваших файлов, вы можете передать любое количество опций --file
, содержащих простые имена файлов, glob или регулярные выражения. По сути, все они передаются в метод name()
Symfony Finder.
humbug --file=NewClass.php --file= * Driver.php
Это никоим образом не ограничивает первоначальную проверку на наличие ошибок во всем наборе тестов, которая по-прежнему выполняется полностью, чтобы убедиться, что все тесты проходят правильно, прежде чем продолжить.
Если вы хотите изменить только несколько конкретных файлов, вы можете передать любое количество опций --path
, содержащих полные имена файлов. Эта опция будет передана в фильтр Closure
, который будет пересекать файлы, найденные с помощью опции config и/или --file
, с файлами, предоставленными вами с помощью опции --path
.
humbug --path=src/Data/NewClass.php --path=src/Driver/Driver.php
Примечание. Это никоим образом не ограничивает первоначальную проверку на наличие ошибок во всем наборе тестов, которая по-прежнему выполняется полностью, чтобы убедиться, что все тесты проходят правильно, прежде чем продолжить.
Инкрементальный анализ (IA) — это экспериментальный незавершенный режим работы, в котором результаты кэшируются локально между запусками и повторно используются там, где это имеет смысл. В настоящее время этот режим работает очень наивно, исключая тестовые прогоны, в которых как непосредственный мутируемый файл, так и соответствующие тесты для мутированной строки не были изменены с момента последнего запуска (что определяется путем сравнения SHA1 задействованных файлов).
humbug --incremental
Режим IA обеспечивает значительное увеличение производительности для относительно стабильных баз кода, и вы можете протестировать его и посмотреть, как он себя поведет в реальной жизни. В будущем ему необходимо будет учитывать изменения в файлах, содержащих родительские классы, импортированные признаки и классы его непосредственных зависимостей, которые оказывают влияние на поведение любого данного объекта.
IA использует локальный постоянный кеш, например /home/padraic/.humbug
.
Мутационное тестирование традиционно было медленным. Идея заключается в том, чтобы повторно запускать набор тестов для каждой сгенерированной мутации. Чтобы значительно ускорить процесс, Humbug делает следующее:
Хотя все это ускоряет Humbug, имейте в виду, что выполнение Humbug будет медленнее, чем модульное тестирование. Двухсекундный набор тестов может потребовать 30 секунд для тестирования мутаций. Или 5 минут. Все зависит от взаимодействия между строками кода, количества тестов, уровня покрытия кода и производительности как кода, так и тестов.
Humbug реализует базовый набор мутаторов, который, по сути, сообщает нам, когда конкретный токен PHP может быть изменен, а также применяет эту мутацию к массиву токенов.
Примечание. Исходный код, хранящийся в функциях (а не в методах класса), в настоящее время не изменяется.
Двоичная арифметика:
Оригинал | Мутировавший | Оригинал | Мутировавший |
---|---|---|---|
+ | - | /= | *= |
- | + | %= | *= |
* | / | **= | /= |
/ | * | & | | |
% | * | | | & |
** | / | ^ | & |
+= | -= | ~ | |
-= | += | >> | << |
*= | /= | << | >> |
Логическая замена:
Это временно охватывает логические мутаторы.
Оригинал | Мутировавший |
---|---|
истинный | ЛОЖЬ |
ЛОЖЬ | истинный |
&& | || |
|| | && |
и | или |
или | и |
! |
Условные границы:
Оригинал | Мутировавший |
---|---|
> | >= |
< | <= |
>= | > |
<= | < |
Отрицательные условные обозначения:
Оригинал | Мутировавший | Оригинал | Мутировавший |
---|---|---|---|
== | != | > | <= |
!= | == | < | >= |
<> | == | >= | < |
=== | !== | <= | > |
!== | === |
Приращения:
Оригинал | Мутировавший |
---|---|
++ | -- |
-- | ++ |
Возвращаемые значения:
Оригинал | Мутировавший | Оригинал | Мутировавший |
---|---|---|---|
вернуть истину; | вернуть ложь; | возврат 1.0>; | вернуть -( + 1); |
вернуть ложь; | вернуть истину; | вернуть $это; | вернуть ноль; |
вернуть 0; | возврат 1; | функция возврата(); | функция(); вернуть ноль; |
возвращаться ; | вернуть 0; | вернуть новый класс; | новый класс; вернуть ноль; |
вернуть 0,0; | вернуть 1,0; | вернуть ( Anything ); | ( Anything ); вернуть ноль; |
вернуть 1,0; | вернуть 0,0; |
Буквальные числа:
Оригинал | Мутировавший |
---|---|
0 | 1 |
1 | 0 |
интервал > 1 | Инт + 1 |
Плавающее >= 1 / <= 2 | Плавающее + 1 |
Плавающее > 2 | 1 |
Если утверждения:
Все операторы if в основном охватываются предыдущими мутаторами, но есть особые случаи, такие как использование собственных функций или методов класса без каких-либо сравнений или операций, например is_int()
или in_array()
. Это не будет охватывать функции, определенные в файлах, поскольку они не существуют до момента выполнения (еще над чем поработать!).
Оригинал | Мутировавший |
---|---|
если (is_int (1)) | если(!is_int(1)) |
Со временем будут добавлены новые мутаторы.
bin/humbug stats ../my-project/humbuglog.json ../my-project/list-of-classes.txt --skip-killed=yes [-vvv]
Анализирует статистику из humbuglog.json или журнала JSON с вашим собственным именем.
Ссылка на интерфейс командной строки:
humbug stats [humbuglog.json location] [class list location] [--skip-killed = yes] [-vvv]
humbuglog.json location, defaults to ./humbuglog.json
class list location, a path to a text file containing full class names, one per line.
only this files-related stats would be shown
--skip-killed=yes is used to completely skip output of "killed" section
various verbosity levels define amount of info to be displayed:
by default, there's one line per class with amount of mutants killed/escaped/errored/timed out (depending on output section)
-v adds one line per each mutant with line number and method name
-vv adds extra line for each mutant, displaying diff view of line mutant is detected in
-vvv shows full diff with several lines before and after
Это можно проверить на самом обмане, запустив в каталоге обманщика:
статистика мусорных контейнеров/обманщиков [-vvv]
Вот краткий список известных проблем:
С разрешения Крейга Дэвиса, который увидел потенциал в некогда пустом репозитории :P.
.:::::::::::...
.::::::::::::::::::::.
.::::::::::::::::::::::::.
::::::::::::::::::::::::::::.
::::::::::::::::::::::::::::::: .,uuu ...
:::::::::::::::::::::::::::::::: dHHHHHLdHHHHb
....:::::::'` ::::::::::::::::::' uHHHHHHHHHHHHHF
.uHHHHHHHHH' ::::::::::::::`. uHHHHHHHHHHHHHP"
HHHHHHHHHHH `:::::::::::',dHHuHHHHHHHHP".g@@g
J"HHHHHHHHHP 4H ::::::::' u$$$.
".HHHHHHHHP" .,uHP :::::' uHHHHHHHHHHP"",e$$$$$c
HHHHHHHF' dHHHHf `````.HHHHHHHHHHP",d$$$$$$$P%C
.dHHHP"" JHHHHbuuuu,JHHHHHHHHP",d$$$$$$$$$e=,z$$$$$$$$ee..
"" .HHHHHHHHHHHHHHHHHP",gdP" ..3$$$Jd$$$$$$$$$$$$$$e.
dHHHHHHHHHHHHHHP".edP " .zd$$$$$$$$$$$"3$$$$$$$$c
`???""??HHHHP",e$$F" .d$,?$$$$$$$$$$$$$F d$$$$$$$$F"
?be.eze$$$$$".d$$$$ $$$E$$$$P".,ede`?$$$$$$$$
4."?$$$$$$$ z$$$$$$ $$$$r.,.e ?$$$$ $$$$$$$$$
'$c "$$$$ .d$$$$$$$ 3$$$.$$$$ 4$$$ d$$$$P"`,,
"""- "$$".`$$" " $$f,d$$P".$$P zeee.zd$$$$$.
ze. .C$C"=^" ..$$$$$$P".$$$'e$$$$$P?$$$$$$
.e$$$$$$$"="$f",c,3eee$$$$$$$$P $$$P'd$$$$"..::.."?$%
4d$$$P d$$$dF.d$$$$$$$$$$$$$$$$f $$$ d$$$" :::::::::.
$$$$$$ d$$$$$ $$$$$$$$$$$$$$$$$$ J$$",$$$'.::::::::::::
"$$$$$$ ?$$$$ d$$$$$$$$$$$$$$$P".dP'e$$$$':::::::::::::::
4$$$$$$c $$$$b`$$$$$$$$$$$P"",e$$",$$$$$' ::::::::::::::::
' ?"?$$$b."$$$$.?$$$$$$P".e$$$$F,d$$$$$F ::::::::::::::::::
"?$$bc."$b.$$$$F z$$P?$$",$$$$$$$ ::::::::::::::::::::
`"$$c"?$$$".$$$)e$$F,$$$$$$$' ::::::::::::::::::::
':. "$b...d$$P4$$$",$$$$$$$" :::::::::::::::::::::
':::: "$$$$$".,"".d$$$$$$$F ::::::::::::::::::::::
:::: be."".d$$$4$$$$$$$$F :::::::::::::::::::::::
:::: "??$$$$$$$$$$?$P" :::::::::::::::::::::::::
:::::: ?$$$$$$$$f .::::::::::::::::::::::::::::
:::::::`"????"".::::::::::::::::::::::::::::::