Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions app/Models/Build.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Models;

use App\Utils\TestDisplay;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
Expand Down Expand Up @@ -400,4 +401,18 @@ public function percentCoverageForPath(string $path): ?float

return ($loctested / $total_lines) * 100;
}

/**
* The number of not-run tests whose details are not "Disabled".
*/
public function notRunTestsWarningCount(): int
{
return $this->tests()
->where('status', Test::NOTRUN)
->where(static function (Builder $query): void {
$query->whereNull('details')
->orWhere('details', '!=', TestDisplay::DISABLED_DETAILS);
})
->count();
}
}
54 changes: 54 additions & 0 deletions app/Utils/TestDisplay.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace App\Utils;

use App\Models\Test;

final class TestDisplay
{
/**
* CTest sets Details="Disabled" for tests marked DISABLED.
*/
public const DISABLED_DETAILS = 'Disabled';

public static function isAcceptableNotRun(?string $details): bool
{
return $details === self::DISABLED_DETAILS;
}

public static function statusColorClass(string $status, ?string $details): string
{
if ($status === Test::NOTRUN && self::isAcceptableNotRun($details)) {
return 'normal';
}

return match ($status) {
Test::PASSED => 'normal',
Test::FAILED => 'error',
Test::NOTRUN => 'warning',
default => '',
};
}

public static function statusTextColorClass(string $status, ?string $details): string
{
return match (self::statusColorClass($status, $details)) {
'normal' => 'normal-text',
'warning' => 'warning-text',
'error' => 'error-text',
default => '',
};
}

public static function graphqlStatusColorClass(string $status, ?string $details): string
{
$dbStatus = match ($status) {
'NOT_RUN' => Test::NOTRUN,
'PASSED' => Test::PASSED,
'FAILED' => Test::FAILED,
default => strtolower($status),
};

return self::statusColorClass($dbStatus, $details);
}
}
14 changes: 14 additions & 0 deletions app/cdash/app/Controller/Api/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

namespace CDash\Controller\Api;

use App\Models\Build as EloquentBuild;
use App\Utils\TestingDay;
use CDash\Database;
use CDash\Model\BuildGroup;
Expand Down Expand Up @@ -1098,6 +1099,7 @@ public function generateBuildResponseFromRow(array $build_array): array|false
}

$test_response['notrun'] = $nnotrun;
$test_response['notrunwarning'] = $this->computeNotRunTestsWarningCount($buildid, $nnotrun);
$test_response['fail'] = $nfail;
$test_response['pass'] = $npass;

Expand Down Expand Up @@ -1555,4 +1557,16 @@ public function recordGenerationTime(array &$response): void
{
$this->pageTimer->end($response);
}

/**
* Count not-run tests that should display as warnings on the index page.
*/
private function computeNotRunTestsWarningCount(int $buildid, int $notRunCount): int
{
if ($notRunCount <= 0) {
return 0;
}

return EloquentBuild::find($buildid)?->notRunTestsWarningCount() ?? 0;
}
}
6 changes: 5 additions & 1 deletion app/cdash/app/Controller/Api/QueryTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use App\Models\PinnedTestMeasurement;
use App\Models\Project as EloquentProject;
use App\Models\TestMeasurement;
use App\Utils\TestDisplay;
use CDash\Database;
use CDash\Model\Build;
use CDash\Model\Project;
Expand Down Expand Up @@ -423,7 +424,10 @@ public function getResponse(): array

case 'notrun':
$test['status'] = 'Not Run';
$test['statusclass'] = 'warning';
$test['statusclass'] = TestDisplay::statusColorClass(
'notrun',
$row->details,
);
break;
}

Expand Down
3 changes: 3 additions & 0 deletions app/cdash/tests/test_testhistory.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ private function generateXML($mm, $timestamp, $include_sporadic, $flaky_passed)
<FullName>./notrun</FullName>
<FullCommandLine></FullCommandLine>
<Results>
<NamedMeasurement type="text/string" name="Exit Code">
<Value>Skipped</Value>
</NamedMeasurement>
<NamedMeasurement type="text/string" name="Command Line">
<Value></Value>
</NamedMeasurement>
Expand Down
5 changes: 5 additions & 0 deletions graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,11 @@ type Build {
"The number of tests not run for this build."
notRunTestsCount: Int @rename(attribute: "testnotrun")

"""
The number of not-run tests counted as warnings (excludes tests whose details are "Disabled").
"""
notRunTestsWarningCount: Int! @method(name: "notRunTestsWarningCount")

"The duration of the test step in seconds."
testDuration: Int! @rename(attribute: "testduration")

Expand Down
2 changes: 1 addition & 1 deletion resources/js/angular/views/partials/build.html
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@
</div>
</td>

<td ng-if="::buildgroup.hastestdata" align="center" ng-class="::{'warning': build.test.notrun > 0, 'normal': build.test.notrun == 0}">
<td ng-if="::buildgroup.hastestdata" align="center" ng-class="::{'warning': build.test.notrunwarning > 0, 'normal': build.test.notrunwarning == 0}">
<div ng-if="::build.hastest"
ng-class="::{'valuewithsub': build.test.nnotrundiffp > 0 || build.test.nnotrundiffn > 0}">
<a class="cdash-link" ng-href="{{ 'builds/' + build.id + '/tests?filters=%7B%22all%22%3A%5B%7B%22eq%22%3A%7B%22status%22%3A%22NOT_RUN%22%7D%7D%5D%7D' }}">
Expand Down
9 changes: 6 additions & 3 deletions resources/js/vue/components/BuildSummary.vue
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ export default {
buildWarningsCount
failedTestsCount
notRunTestsCount
notRunTestsWarningCount
site {
id
name
Expand All @@ -539,6 +540,7 @@ export default {
buildWarningsCount
failedTestsCount
notRunTestsCount
notRunTestsWarningCount
}
nextBuild: build(id: $nextId) @include(if: $hasNext) {
id
Expand All @@ -548,6 +550,7 @@ export default {
buildWarningsCount
failedTestsCount
notRunTestsCount
notRunTestsWarningCount
}
}
`,
Expand Down Expand Up @@ -576,7 +579,7 @@ export default {
nerrors: Math.max(0, prev.buildErrorsCount),
nwarnings: Math.max(0, prev.buildWarningsCount),
ntestfailed: Math.max(0, prev.failedTestsCount),
ntestnotrun: Math.max(0, prev.notRunTestsCount),
ntestnotrun: Math.max(0, prev.notRunTestsWarningCount),
};
} else {
this.cdash.previousbuild = null;
Expand All @@ -591,7 +594,7 @@ export default {
nerrors: Math.max(0, next.buildErrorsCount),
nwarnings: Math.max(0, next.buildWarningsCount),
ntestfailed: Math.max(0, next.failedTestsCount),
ntestnotrun: Math.max(0, next.notRunTestsCount),
ntestnotrun: Math.max(0, next.notRunTestsWarningCount),
};
} else {
this.cdash.nextbuild = null;
Expand All @@ -616,7 +619,7 @@ export default {

this.cdash.test = {
nfailed: Math.max(0, build.failedTestsCount),
nnotrun: Math.max(0, build.notRunTestsCount),
nnotrun: Math.max(0, build.notRunTestsWarningCount),
};

this.cdash.projectname_encoded = encodeURIComponent(build.project.name);
Expand Down
18 changes: 3 additions & 15 deletions resources/js/vue/components/BuildTestsPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import LoadingIndicator from './shared/LoadingIndicator.vue';
import BuildSummaryCard from './shared/BuildSummaryCard.vue';
import BuildSidebar from './shared/BuildSidebar.vue';
import { DateTime } from 'luxon';
import { testStatusToColorClass } from './shared/TestDisplay';

const TEST_QUERY = gql`
query(
Expand Down Expand Up @@ -325,14 +326,14 @@ export default {
value: edge.node.status,
text: this.humanReadableTestStatus(edge.node.status),
href: `${this.$baseURL}/tests/${edge.node.id}`,
classes: [this.testStatusToColorClass(edge.node.status)],
classes: [testStatusToColorClass(edge.node.status, edge.node.details)],
},
subProject: edge.subProject ?? '',
timeStatus: {
value: edge.node.timeStatusCategory,
text: this.humanReadableTestStatus(edge.node.timeStatusCategory),
href: `${this.$baseURL}/tests/${edge.node.id}?graph=time`,
classes: [this.testStatusToColorClass(edge.node.timeStatusCategory)],
classes: [testStatusToColorClass(edge.node.timeStatusCategory, edge.node.details)],
},
history: {
value: '',
Expand All @@ -349,19 +350,6 @@ export default {
},

methods: {
testStatusToColorClass(status) {
switch (status) {
case 'PASSED':
return 'normal';
case 'FAILED':
return 'error';
case 'NOT_RUN':
return 'warning';
default:
return '';
}
},

humanReadableTestStatus(status) {
switch (status) {
case 'PASSED':
Expand Down
3 changes: 2 additions & 1 deletion resources/js/vue/components/ProjectSettings/GeneralTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@
</FormSection>

<FormSection
title="Tests"
title="Testing"
section-id="Testing"
>
<CheckboxField
v-model="form.enableTestTiming"
Expand Down
17 changes: 17 additions & 0 deletions resources/js/vue/components/ProjectSettingsPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,22 @@ export default {
currentSection: 'general',
};
},

mounted() {
this.navigateToHashSection();
},

methods: {
navigateToHashSection() {
if (window.location.hash !== '#Testing') {
return;
}

this.currentSection = 'general';
this.$nextTick(() => {
document.getElementById('Testing')?.scrollIntoView();
});
},
},
};
</script>
9 changes: 9 additions & 0 deletions resources/js/vue/components/TestDetailsPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ import {
faChartLine,
faLink,
} from '@fortawesome/free-solid-svg-icons';
import { isAcceptableNotRun } from './shared/TestDisplay';

export default {
name: 'TestDetails',
Expand Down Expand Up @@ -517,6 +518,14 @@ export default {
},

testStatusPillClass() {
if (!this.test) {
return 'tw-bg-neutral tw-text-neutral-content';
}

if (this.test.status === 'NOT_RUN' && isAcceptableNotRun(this.test.details)) {
return 'tw-bg-success tw-text-success-content';
}

switch (this.test.status) {
case 'PASSED':
return 'tw-bg-success tw-text-success-content';
Expand Down
28 changes: 21 additions & 7 deletions resources/js/vue/components/shared/BuildSummaryCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ export default {
passedTestsCount
failedTestsCount
notRunTestsCount
notRunTestsWarningCount
site {
id
name
Expand Down Expand Up @@ -455,9 +456,15 @@ export default {
return 'No Submission';
}

const notRunWarningCount = Math.max(0, this.build.notRunTestsWarningCount);
const notRunSkippedCount = Math.max(0, this.build.notRunTestsCount - notRunWarningCount);

let retval = '';
if (this.build.notRunTestsCount > 0) {
retval += `${this.build.notRunTestsCount} Not Run${this.commaSeparator(this.build.failedTestsCount > 0 || this.build.passedTestsCount)}`;
if (notRunWarningCount > 0) {
retval += `${notRunWarningCount} Not Run${this.commaSeparator(this.build.failedTestsCount > 0 || this.build.passedTestsCount > 0 || notRunSkippedCount > 0)}`;
}
if (notRunSkippedCount > 0) {
retval += `${notRunSkippedCount} Skipped${this.commaSeparator(this.build.failedTestsCount > 0 || this.build.passedTestsCount > 0)}`;
}
if (this.build.failedTestsCount > 0) {
retval += `${this.build.failedTestsCount} Failed${this.commaSeparator(this.build.passedTestsCount)}`;
Expand Down Expand Up @@ -565,19 +572,26 @@ export default {
testColor() {
if (this.build.failedTestsCount > 0) {
return 'tw-bg-red-400';
} else {
return 'tw-bg-green-400';
}
if (this.build.notRunTestsWarningCount > 0) {
return 'tw-bg-orange-400';
}

return 'tw-bg-green-400';
},

testHighlightColor() {
if (!this.hasTest) {
return 'tw-border-x-gray-400';
} else if (this.build.failedTestsCount > 0) {
}
if (this.build.failedTestsCount > 0) {
return 'tw-border-x-red-400';
} else {
return 'tw-border-x-green-400';
}
if (this.build.notRunTestsWarningCount > 0) {
return 'tw-border-x-orange-400';
}

return 'tw-border-x-green-400';
},

/**
Expand Down
11 changes: 10 additions & 1 deletion resources/js/vue/components/shared/FormSection.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<template>
<section class="tw-container tw-mx-auto">
<section
:id="sectionId"
class="tw-container tw-mx-auto"
>
<h4 class="tw-text-xl tw-font-semibold tw-border-b tw-pb-2 tw-mb-2">
{{ title }}
</h4>
Expand All @@ -18,6 +21,12 @@ export default {
type: String,
required: true,
},

sectionId: {
type: String,
required: false,
default: null,
},
},
};
</script>
Loading