Compare commits

...

30 Commits

Author SHA1 Message Date
James
96ef72c71c bug: null error on new issue 2020-05-03 09:18:42 +01:00
James
9b2546c3ee add @silent and @normal commands 2020-04-17 12:31:39 +01:00
James
c309f2b225 add "@bot quiet" to suppress repeat warnings 2020-04-04 11:10:29 +01:00
James
e2e428b28c use real array for xml @attibutes 2020-02-15 13:43:21 +00:00
James
5289eaedaf add missing var 2020-02-15 13:26:24 +00:00
James
4ae0e04391 fix comments 2020-02-15 13:25:41 +00:00
James
b75e3af1b5 fix wording 2020-02-15 13:24:29 +00:00
James
ce7c917874 reorder for readability and comment 2020-02-15 13:23:44 +00:00
James
0ce38258dc fix comments 2020-02-15 13:21:32 +00:00
James
8f41a5583b tidy unused vars 2020-02-15 13:20:30 +00:00
James
e8ef5f535c make repeat fails just link to previous post rather than posting again 2020-02-15 13:19:09 +00:00
James
a5be144041 remove GiteaTitle env var, change title format to allow skipped/failed to use same issue 2020-02-13 13:48:21 +00:00
James
30db5377eb add closing of failed tests 2020-02-11 20:12:34 +00:00
James
b2c3faf5c1 fix class errors 2020-02-11 15:58:40 +00:00
James
811f953e6e only post failed tests. comment if already open, else create new issue 2020-02-11 15:51:41 +00:00
James
afc4c618f4 fail count 2020-02-10 18:01:10 +00:00
James
1d2ca239e7 refactor to use xml and not testdox for generating the report
also add custim GiteaTitle env var for setting the title
2020-02-09 12:24:14 +00:00
James
05d4e2e3c1 dont post results if no url set 2020-02-03 15:25:18 +00:00
James
7fada2c155 fix to specify release id 2020-01-29 18:08:51 +00:00
920b8a3cc1 Update 'composer.json' 2020-01-29 16:28:38 +00:00
James
71cffd1614 dont post blank reports 2019-09-25 17:58:56 +01:00
James
994768ca9d fix indenting 2019-09-25 09:23:48 +01:00
James
1cbcac0361 call parent functions so default output not lost 2019-09-25 08:51:37 +01:00
James
bcea50c5dd delete screenshots after uploading 2019-09-25 08:51:21 +01:00
James
0c98200fc2 remove debug 2019-09-23 16:13:57 +01:00
James
e4c9d97697 add selenium url to test results 2019-09-23 16:13:11 +01:00
James
495d4e0d26 upload screenshots 2019-09-23 12:18:16 +01:00
6c0873fc6f Update 'README.md' 2019-09-22 20:09:53 +01:00
cc0eec3b4a Update 'README.md' 2019-09-22 20:03:33 +01:00
James
676c2215c7 update readme 2019-09-22 19:58:46 +01:00
6 changed files with 284 additions and 74 deletions

View File

@ -1 +1,19 @@
Post PHPUnit test results to Gitea
Enable in phpunit.xml with
```plain
<phpunit ... printerClass="JHodges\GiteaBotPHPUnit\ResultPrinter">
<php>
<env name="GiteaUrl" value="https://try.gitea.io/api/v1/"/>
<env name="GiteaUser" value="bot"/>
<!--env name="GiteaPass" value="xxx"/--> <!--probably set this on the machine env-->
<env name="GiteaRepoUser" value="bobemoe"/>
<env name="GiteaRepo" value="test"/>
</php>
<logging>
<log type="junit" target="/tmp/logfile.xml"/>
</logging>
```

View File

@ -8,7 +8,7 @@
}
],
"require": {
"jhodges/giteabot": "~1.2.0"
"jhodges/giteabot": "dev-master"
},
"autoload": {
"psr-4": {

160
src/PostFailedTests.php Normal file
View File

@ -0,0 +1,160 @@
<?php
namespace JHodges\GiteaBotPHPUnit;
use \JHodges\GiteaBot\Client;
/**
* creates a new issue for each failed test
* if it already exists then report is added as a comment
* if exact error exists as body or comment then just link to it instead of posting again
* if it passes then the issue is closed
*/
final class PostFailedTests{
private $repo=null;
private $xml=null;
function __construct($xml_path){
$this->xml = simplexml_load_file($xml_path);
}
public function post($url, $user, $pass, $repoUser, $repo){
if(!$url) return;
// open connection and repo
$client=new Client($url, $user, $pass, true);
$this->repo=$client->getRepo($repoUser, $repo);
$this->process($this->xml);
}
private function process($item){
if(isset($item->testcase)){
foreach($item->testcase as $testcase) {
$att = current($testcase->attributes());
$name=$att['class'].'::'.$att['name'];
$fail=false;
foreach($testcase as $k=>$v){
$this->fail($name,$att,$k,$v);
$fail=true;
}
if(!$fail){
$this->success($name,$att);
}
}
}
if(isset($item->testsuite)){
foreach($item->testsuite as $testsuite) {
$this->process($testsuite);
}
}
}
private function success($name,$att){
$issue=$this->repo->getIssues(['q' => $name])[0]??null;
if($issue){
$issue->state='closed';
$issue->save();
}
}
private function fail($name,$att,$error,$message){
//stick the error type into the atts array
$att['result']=$error;
//trim the message
$message=trim($message);
// get any existing issue
$issue=$this->repo->getIssues(['q' => $name])[0]??null;
// if existing issue.
if($issue){
// are there any instructions in comments?
$quiet=$silent=false;
foreach($issue->getComments() as $comment){
if( stripos('@bot quiet',$comment->body)!==false ){
$quiet=true;
$silent=false;
}
if( stripos('@bot silent',$comment->body)!==false ){
$silent=true;
$quiet=true;
}
if( stripos('@bot normal',$comment->body)!==false ){
$silent=false;
$quiet=false;
}
}
if($silent){return;}
//is the error the same?
if( $this->doesMessageMatch($issue->body,$message,$att) ){
if($quiet){return;}
$issue->addComment("Failed again. Same errors as [above]($issue->html_url#issue-{$issue->id})");
return;
}else{
foreach($issue->getComments() as $comment){
if( $this->doesMessageMatch($comment->body,$message,$att) ){
if($quiet){return;}
$issue->addComment("Failed again. Same errors as [above]($issue->html_url#issuecomment-{$comment->id})");
return;
}
}
}
}
//so its a new issue or changed error, lets upload screenshot and compose the body
$issueBody='';
if(file_exists("/tmp/$name.png")){
$data=$this->repo->addReleaseAttachment(1,"/tmp/$name.png");
$url=$data->browser_download_url;
$issueBody.="\n![]($url)\n";
unlink("/tmp/$name.png");
}
if($message) $issueBody.="```plain\n$message\n```\n";
foreach($att as $k=>$v){
$issueBody.=" * $k = $v\n";
}
//post the body
if($issue){
$issue->addComment($issueBody);
}else{
$issue=$this->repo->createIssue([
'title'=>'Failed test '.$name,
'body'=>$issueBody
]);
}
}
private function doesMessageMatch($body,$message,$att){
// extract the old message
preg_match('#```plain\n(.*)\n```#s',$body,$match);
$messageOld=$match[1]??'';
// return false if not the same
if( $message != $messageOld ){
return false;
}
// extract the old atts
$attOld=[];
preg_match_all('# \* (.*?) = (.*)#',$body,$m);
foreach($m[0]??[] as $k=>$v){
$attOld[$m[1][$k]]=$m[2][$k];
}
// make sure all current attributes (except time) are the same as old
// return false on first mis-match
foreach($att as $k=>$v){
if($k=='time') continue;
if(($attOld[$k]??null) != $v){
return false;
}
}
// all matches, error message is the same
return true;
}
}

80
src/PostFullReport.php Normal file
View File

@ -0,0 +1,80 @@
<?php
namespace JHodges\GiteaBotPHPUnit;
use \JHodges\GiteaBot\Client;
final class PostFullReport{
private $report;
private $level=0;
private $failCount=0;
function __construct($xml_path){
$this->xml = simplexml_load_file($xml_path);
}
public function post($url, $user, $pass, $repoUser, $repo){
if(!$url) return;
// open connection and repo
$this->client=new Client($url, $user, $pass);
$this->repo=$this->client->getRepo($repoUser, $repo);
$this->process($this->xml); //process xml and upload screenshots
// create the issue
if(trim($this->report)){
$issue=$this->repo->createIssue([
'title'=>'Test Results',
'body'=>$this->report
]);
}
}
public function getFailCount(){
return $this->failCount;
}
private function process($item){
$this->level++;
if(isset($item->testcase)){
foreach($item->testcase as $testcase) {
$att=$testcase->attributes();
$failmsg='';
foreach($testcase as $k=>$v){
$failmsg="(**$k**)\n";
if(trim($v)) $failmsg.="```plain\n$v\n```\n";
}
if($failmsg){
$this->failCount++;
$this->report.=" * [ ] {$att->name[0]} $failmsg\n";
}else{
$this->report.=" * [x] {$att->name[0]}\n";
}
$name=$testcase->attributes()->class[0].'::'.$testcase->attributes()->name[0];
if(file_exists("/tmp/$name.png")){
$data=$this->repo->addReleaseAttachment(1,"/tmp/$name.png");
$url=$data->browser_download_url;
$img="\n![]($url)\n";
unlink("/tmp/$name.png");
$this->report.="$img\n";
}
}
}
if(isset($item->testsuite)){
foreach($item->testsuite as $testsuite) {
$att=$testsuite->attributes();
$this->report.=str_repeat('#',$this->level)." {$att->name[0]}\n".
"tests: {$att->tests[0]}".
", assertions: {$att->assertions[0]}".
", errors: {$att->errors[0]}".
", failures: {$att->failures[0]}".
", skipped: {$att->skipped[0]}".
", time: {$att->time[0]}".
"\n";
$this->process($testsuite);
}
}
$this->level--;
}
}

View File

@ -1,48 +0,0 @@
<?php
namespace JHodges\GiteaBotPHPUnit;
use \JHodges\GiteaBot\Client;
final class Poster{
private $report;
function __construct($testdox_path,$xml_path){
$testdox=file_get_contents($testdox_path);
$testdox=preg_replace('# \[#',' * [',$testdox);
$this->report.=$testdox;
$xml = simplexml_load_file($xml_path);
$this->process($xml);
}
public function post($url, $user, $pass, $repoUser, $repo){
// open connection and repo
$client=new Client($url, $user, $pass);
$repo=$client->getRepo($repoUser, $repo);
// create the issue
$issue=$repo->createIssue([
'title'=>'Test Results',
'body'=>$this->report
]);
}
private function process($item){
if(isset($item->testcase)){
foreach($item->testcase as $testcase) {
foreach($testcase as $k=>$v){
$this->report.="\n```plain\n".print_r($testcase,true)."\n```";
}
}
}
if(isset($item->testsuite)){
foreach($item->testsuite as $testsuite) {
$this->process($testsuite);
}
}
}
}

View File

@ -1,34 +1,34 @@
<?php
namespace JHodges\GiteaBotPHPUnit;
class ResultPrinter extends \PHPUnit\TextUI\ResultPrinter
{
class ResultPrinter extends \PHPUnit\TextUI\ResultPrinter{
public function __construct($out = null, $verbose = false, $colors = self::COLOR_DEFAULT, $debug = false, $numberOfColumns = 80){
parent::__construct($out, $verbose, $colors , $debug , $numberOfColumns);
}
public function __construct($out = null, $verbose = false, $colors = self::COLOR_DEFAULT, $debug = false, $numberOfColumns = 80){
parent::__construct($out, $verbose, $colors , $debug , $numberOfColumns);
}
public function printResult(\PHPUnit\Framework\TestResult $result)
{
$poster=new \JHodges\GiteaBotPHPUnit\Poster('/tmp/testdox.txt','/tmp/logfile.xml');
$poster->post(
getenv('GiteaUrl'),
getenv('GiteaUser'),
getenv('GiteaPass'),
getenv('GiteaRepoUser'),
getenv('GiteaRepo')
);
}
public function printResult(\PHPUnit\Framework\TestResult $result){
parent::printResult($result);
$poster=new \JHodges\GiteaBotPHPUnit\PostFailedTests('/tmp/logfile.xml');
$poster->post(
getenv('GiteaUrl'),
getenv('GiteaUser'),
getenv('GiteaPass'),
getenv('GiteaRepoUser'),
getenv('GiteaRepo')
);
}
protected function printHeader()
{
}
protected function printHeader(){
parent::printHeader();
}
public function messageProcessor(array $record)
{
}
public function messageProcessor(array $record){
parent::messageProcessor($record);
}
public function suiteNameProcessor(array $record){
parent::suiteNameProcessor($record);
}
public function suiteNameProcessor(array $record)
{
}
}