Add a list of recent failed tests to front page

This commit adds a new table to the front page which contains a list
of the tests which failed as part of the 10 most recent failed runs.

Change-Id: I5ff8ed38742d31e0b1a972901b7907030ec99bea
This commit is contained in:
Matthew Treinish 2016-01-15 15:48:15 -05:00
parent d4ecb58644
commit bdbd42e9c7
No known key found for this signature in database
GPG Key ID: FD12A0F214C9E177
7 changed files with 102 additions and 2 deletions

View File

@ -109,16 +109,19 @@ function HomeController($scope, healthService, projectService, viewService, $loc
processData(response.data);
vm.loaded = true;
});
healthService.getRecentFailedTests().then(function(response) {
vm.recentTests = response.data;
});
};
// ViewModel
var vm = this;
vm.loadData = loadData;
vm.groupKey = viewService.groupKey();
vm.searchProject = $location.search().searchProject || '';
vm.loaded = false;
vm.hold = 0;
vm.recentTests = [];
configurePeriods();
loadData();

View File

@ -129,6 +129,13 @@ function HealthService($http, config) {
});
});
};
service.getRecentFailedTests = function(options) {
return config.get().then(function(config) {
return $http.jsonp(config.apiRoot + '/tests/recent/fail', {
params: { callback: 'JSON_CALLBACK' }
});
});
};
return service;
}

View File

@ -35,6 +35,35 @@
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Failed Tests in Last 10 Failed Runs</h3>
</div>
<div class="panel-body">
<table class="table">
<thead>
<tr>
<th>Test ID</th>
<th>Run Link</th>
<th>Start Time</th>
<th>Stop Time</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="testRun in home.recentTests">
<td><a ui-sref="test({ testId: testRun.test_id })"}>{{ testRun.test_id | limitTo: 80 }}</td>
<td><a href="{{ testRun.link }}">{{ testRun.link | limitTo: -30 }}</a></td>
<td>{{ testRun.start_time }}</td>
<td>{{ testRun.stop_time }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<form>

View File

@ -291,6 +291,21 @@ def get_recent_runs(run_metadata_key, value):
return jsonify(runs)
@app.route('/tests/recent/<string:status>', methods=['GET'])
def get_recent_test_status(status):
session = get_session()
num_runs = flask.request.args.get('num_runs', 10)
failed_runs = api.get_recent_failed_runs(num_runs, session)
test_runs = api.get_test_runs_by_status_for_run_ids(status, failed_runs,
session=session)
output = []
for run in test_runs:
run['start_time'] = run['start_time'].isoformat()
run['stop_time'] = run['stop_time'].isoformat()
output.append(run)
return jsonify(output)
@app.route('/run/<string:run_id>/tests', methods=['GET'])
def get_tests_from_run(run_id):
session = get_session()

View File

@ -732,3 +732,30 @@ class TestRestAPI(base.TestCase):
u'status': 'fail'
}]
self.assertEqual(expected_res, response_data)
@mock.patch('subunit2sql.db.api.get_recent_failed_runs',
return_value=['a_convincing_id'])
@mock.patch('subunit2sql.db.api.get_test_runs_by_status_for_run_ids',
return_value=[
{
'test_id': u'fake_test',
'link': u'fake_url',
'start_time': timestamp_a,
'stop_time': timestamp_b,
}
])
def test_get_recent_test_failures(self, db_mock, recent_mock):
api.Session = mock.MagicMock()
res = self.app.get('/tests/recent/fail')
self.assertEqual(200, res.status_code)
db_mock.assert_called_once_with('fail', ['a_convincing_id'],
session=api.Session())
response_data = json.loads(res.data)
expected_resp = [
{
'test_id': u'fake_test',
'link': u'fake_url',
'start_time': timestamp_a.isoformat(),
'stop_time': timestamp_b.isoformat(),
}]
self.assertEqual(expected_resp, response_data)

View File

@ -3,7 +3,7 @@
# process, which may cause wedges in the gate later.
pbr>=1.6 # Apache-2.0
Flask<1.0,>=0.10 # BSD
subunit2sql>=1.2.0 # Apache-2.0
subunit2sql>=1.3.0 # Apache-2.0
SQLAlchemy<1.1.0,>=1.0.10 # MIT
flask-jsonpify # MIT
PyMySQL>=0.6.2 # MIT License

View File

@ -14,6 +14,20 @@ describe('HomeController', function() {
}
}
};
var mockRecentFailed = [
{
'link': 'http://logs.openstack.org/97/280597/1/gate/gate-tempest-dsvm-ironic-pxe_ipa/61f4153',
'start_time': '2016-02-17T11:38:43.185384',
'stop_time': '2016-02-17T11:50:04.465870',
'test_id': 'ironic.test_baremetal_basic_ops.BaremetalBasicOps.test_baremetal_server_ops'
},
{
'link': 'http://logs.openstack.org/49/277949/2/gate/gate-tempest-dsvm-ironic-pxe_ipa/8ac452c',
'start_time': '2016-02-17T10:29:32.448360',
'stop_time': '2016-02-17T10:44:33.880733',
'test_id': 'ironic.test_baremetal_basic_ops.BaremetalBasicOps.test_baremetal_server_ops'
}
];
beforeEach(inject(function($rootScope, _$controller_) {
$scope = $rootScope.$new();
@ -27,6 +41,11 @@ describe('HomeController', function() {
return {
then: function(callback) { callback(mockMetadataKeysResponse); }
};
},
getRecentFailedTests: function() {
return {
then: function(callback) { callback(mockRecentFailed); }
};
}
};
projectService = {