Skip to content

Commit

Permalink
[ML] Tests for ML annotations feature. (elastic#27994)
Browse files Browse the repository at this point in the history
Adds unit/integration tests for various parts of the code base affected by the annotations feature.
  • Loading branch information
walterra authored Jan 4, 2019
1 parent 3496dff commit 99f9929
Show file tree
Hide file tree
Showing 15 changed files with 711 additions and 1 deletion.
135 changes: 135 additions & 0 deletions x-pack/plugins/ml/common/types/__mocks__/job_config_farequote.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
{
"job_id": "farequote",
"job_type": "anomaly_detector",
"job_version": "7.0.0",
"description": "",
"create_time": 1546418356716,
"finished_time": 1546418359427,
"established_model_memory": 42102,
"analysis_config": {
"bucket_span": "15m",
"summary_count_field_name": "doc_count",
"detectors": [
{
"detector_description": "count",
"function": "count",
"detector_index": 0
}
],
"influencers": []
},
"analysis_limits": {
"model_memory_limit": "10mb",
"categorization_examples_limit": 4
},
"data_description": {
"time_field": "@timestamp",
"time_format": "epoch_ms"
},
"model_plot_config": {
"enabled": true
},
"model_snapshot_retention_days": 1,
"custom_settings": {
"created_by": "single-metric-wizard"
},
"model_snapshot_id": "1546418359",
"model_snapshot_min_version": "6.4.0",
"results_index_name": "shared",
"data_counts": {
"job_id": "farequote",
"processed_record_count": 479,
"processed_field_count": 479,
"input_bytes": 21554,
"input_field_count": 479,
"invalid_date_count": 0,
"missing_field_count": 0,
"out_of_order_timestamp_count": 0,
"empty_bucket_count": 0,
"sparse_bucket_count": 0,
"bucket_count": 478,
"earliest_record_timestamp": 1454804096000,
"latest_record_timestamp": 1455234298000,
"last_data_time": 1546418357578,
"input_record_count": 479
},
"model_size_stats": {
"job_id": "farequote",
"result_type": "model_size_stats",
"model_bytes": 42102,
"total_by_field_count": 3,
"total_over_field_count": 0,
"total_partition_field_count": 2,
"bucket_allocation_failures_count": 0,
"memory_status": "ok",
"log_time": 1546418359000,
"timestamp": 1455232500000
},
"datafeed_config": {
"datafeed_id": "datafeed-farequote",
"job_id": "farequote",
"query_delay": "115823ms",
"indices": [
"farequote"
],
"types": [],
"query": {
"bool": {
"must": [
{
"query_string": {
"query": "*",
"fields": [],
"type": "best_fields",
"default_operator": "or",
"max_determinized_states": 10000,
"enable_position_increments": true,
"fuzziness": "AUTO",
"fuzzy_prefix_length": 0,
"fuzzy_max_expansions": 50,
"phrase_slop": 0,
"analyze_wildcard": true,
"escape": false,
"auto_generate_synonyms_phrase_query": true,
"fuzzy_transpositions": true,
"boost": 1
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
},
"aggregations": {
"buckets": {
"date_histogram": {
"field": "@timestamp",
"interval": 900000,
"offset": 0,
"order": {
"_key": "asc"
},
"keyed": false,
"min_doc_count": 0
},
"aggregations": {
"@timestamp": {
"max": {
"field": "@timestamp"
}
}
}
}
},
"scroll_size": 1000,
"chunking_config": {
"mode": "manual",
"time_span": "900000000ms"
},
"delayed_data_check_config": {
"enabled": true
},
"state": "stopped"
},
"state": "closed"
}
23 changes: 23 additions & 0 deletions x-pack/plugins/ml/common/types/annotations.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ANNOTATION_TYPE } from '../constants/annotations';

import { isAnnotation, isAnnotations } from './annotations';

describe('Types: Annotations', () => {
test('Minimal integrity check.', () => {
const annotation = {
job_id: 'id',
annotation: 'Annotation text',
timestamp: 0,
type: ANNOTATION_TYPE.ANNOTATION,
};

expect(isAnnotation(annotation)).toBe(true);
expect(isAnnotations([annotation])).toBe(true);
});
});
15 changes: 15 additions & 0 deletions x-pack/plugins/ml/common/types/jobs.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import jobConfigFarequote from './__mocks__/job_config_farequote';
import { isMlJob, isMlJobs } from './jobs';

describe('Types: Jobs', () => {
test('Minimal integrity check.', () => {
expect(isMlJob(jobConfigFarequote)).toBe(true);
expect(isMlJobs([jobConfigFarequote])).toBe(true);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"timestamp": 1455026177994,
"end_timestamp": 1455041968976,
"annotation": "Major spike.",
"job_id": "farequote",
"type": "annotation",
"create_time": 1546417097181,
"create_username": "<user unknown>",
"modified_time": 1546417097181,
"modified_username": "<user unknown>",
"_id": "KCCkDWgB_ZdQ1MFDSYPi"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AnnotationsTable Initialization with annotations prop. 1`] = `
<EuiInMemoryTable
className="eui-textOverflowWrap"
columns={
Array [
Object {
"field": "annotation",
"name": "Annotation",
"sortable": true,
},
Object {
"dataType": "date",
"field": "timestamp",
"name": "From",
"render": [Function],
"sortable": true,
},
Object {
"dataType": "date",
"field": "end_timestamp",
"name": "To",
"render": [Function],
"sortable": true,
},
Object {
"dataType": "date",
"field": "create_time",
"name": "Creation date",
"render": [Function],
"sortable": true,
},
Object {
"field": "create_username",
"name": "Created by",
"sortable": true,
},
Object {
"dataType": "date",
"field": "modified_time",
"name": "Last modified date",
"render": [Function],
"sortable": true,
},
Object {
"field": "modified_username",
"name": "Last modified by",
"sortable": true,
},
Object {
"align": "right",
"name": "View",
"render": [Function],
"width": "60px",
},
]
}
compressed={true}
items={
Array [
Object {
"_id": "KCCkDWgB_ZdQ1MFDSYPi",
"annotation": "Major spike.",
"create_time": 1546417097181,
"create_username": "<user unknown>",
"end_timestamp": 1455041968976,
"job_id": "farequote",
"modified_time": 1546417097181,
"modified_username": "<user unknown>",
"timestamp": 1455026177994,
"type": "annotation",
},
]
}
pagination={
Object {
"pageSizeOptions": Array [
5,
10,
25,
],
}
}
responsive={true}
rowProps={[Function]}
sorting={
Object {
"sort": Object {
"direction": "asc",
"field": "timestamp",
},
}
}
/>
`;

exports[`AnnotationsTable Initialization with job config prop. 1`] = `
<EuiFlexGroup
alignItems="stretch"
component="div"
direction="row"
gutterSize="l"
justifyContent="spaceAround"
responsive={true}
wrap={false}
>
<EuiFlexItem
component="div"
grow={false}
>
<EuiLoadingSpinner
size="l"
/>
</EuiFlexItem>
</EuiFlexGroup>
`;

exports[`AnnotationsTable Minimal initialization without props. 1`] = `
<EuiCallOut
color="primary"
iconType="iInCircle"
size="m"
title="No annotations created for this job"
/>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import jobConfig from '../../../../common/types/__mocks__/job_config_farequote';

import ngMock from 'ng_mock';
import expect from 'expect.js';
import sinon from 'sinon';

import { ml } from '../../../services/ml_api_service';

describe('ML - <ml-annotation-table>', () => {
let $scope;
let $compile;

beforeEach(ngMock.module('kibana'));
beforeEach(() => {
ngMock.inject(function ($injector) {
$compile = $injector.get('$compile');
const $rootScope = $injector.get('$rootScope');
$scope = $rootScope.$new();
});
});

afterEach(() => {
$scope.$destroy();
});

it('Plain initialization doesn\'t throw an error', () => {
expect(() => {
$compile('<ml-annotation-table />')($scope);
}).to.not.throwError();
});

it('Initialization with empty annotations array doesn\'t throw an error', () => {
expect(() => {
$compile('<ml-annotation-table annotations="[]" />')($scope);
}).to.not.throwError();
});

it('Initialization with job config doesn\'t throw an error', () => {
const getAnnotationsStub = sinon.stub(ml.annotations, 'getAnnotations').resolves({ annotations: [] });

expect(() => {
$scope.jobs = [jobConfig];
$compile('<ml-annotation-table jobs="jobs" />')($scope);
}).to.not.throwError();

getAnnotationsStub.restore();
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ class AnnotationsTable extends Component {
}

componentDidMount() {
if (this.props.annotations === undefined) {
if (
this.props.annotations === undefined &&
Array.isArray(this.props.jobs) && this.props.jobs.length > 0
) {
this.getAnnotations();
}
}
Expand All @@ -118,6 +121,7 @@ class AnnotationsTable extends Component {
if (
this.props.annotations === undefined &&
this.state.isLoading === false &&
Array.isArray(this.props.jobs) && this.props.jobs.length > 0 &&
this.state.jobId !== this.props.jobs[0].job_id
) {
this.getAnnotations();
Expand Down
Loading

0 comments on commit 99f9929

Please sign in to comment.