[ML] Add functional tests for analytics UI: classification jobs (#56912)

* add classification functional tests

* remove unneeded testing tag

* update jobId and description per suggestion

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Melissa Alvarez 2020-02-10 09:09:55 -05:00 committed by GitHub
parent b13acff23d
commit bcbb16d1f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 1743 additions and 3 deletions

View file

@ -218,7 +218,10 @@ export const EvaluatePanel: FC<Props> = ({ jobConfig, jobStatus, searchQuery })
}
return (
<EuiPanel style={{ width: `${panelWidth}px` }}>
<EuiPanel
data-test-subj="mlDFAnalyticsClassificationExplorationEvaluatePanel"
style={{ width: `${panelWidth}px` }}
>
<EuiFlexGroup direction="column" gutterSize="s">
<EuiFlexItem>
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween">
@ -337,6 +340,7 @@ export const EvaluatePanel: FC<Props> = ({ jobConfig, jobStatus, searchQuery })
</EuiFlexItem>
<EuiFlexItem grow={false} style={{ width: '90%' }}>
<EuiDataGrid
data-test-subj="mlDFAnalyticsClassificationExplorationConfusionMatrix"
aria-label="Classification confusion matrix"
columns={columns}
columnVisibility={{ visibleColumns, setVisibleColumns }}

View file

@ -401,7 +401,11 @@ export const ResultsTable: FC<Props> = React.memo(
: searchError;
return (
<EuiPanel grow={false} id="mlDataFrameAnalyticsTableResultsPanel">
<EuiPanel
grow={false}
id="mlDataFrameAnalyticsTableResultsPanel"
data-test-subj="mlDFAnalyticsClassificationExplorationTablePanel"
>
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween" responsive={false}>
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="s">

View file

@ -0,0 +1,174 @@
/*
* 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 expect from '@kbn/expect';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default function({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const ml = getService('ml');
describe('classification creation', function() {
this.tags(['smoke']);
before(async () => {
await esArchiver.load('ml/bm_classification');
});
after(async () => {
await ml.api.cleanMlIndices();
await esArchiver.unload('ml/bm_classification');
});
const testDataList = [
{
suiteTitle: 'bank marketing',
jobType: 'classification',
jobId: `bm_1_${Date.now()}`,
jobDescription:
"Classification job based on 'bank-marketing' dataset with dependentVariable 'y' and trainingPercent '20'",
source: 'bank-marketing*',
get destinationIndex(): string {
return `dest_${this.jobId}`;
},
dependentVariable: 'y',
trainingPercent: '20',
modelMemory: '105mb',
createIndexPattern: true,
expected: {
row: {
type: 'classification',
status: 'stopped',
progress: '100',
},
},
},
];
for (const testData of testDataList) {
describe(`${testData.suiteTitle}`, function() {
after(async () => {
await ml.api.deleteIndices(testData.destinationIndex);
});
it('loads the data frame analytics page', async () => {
await ml.navigation.navigateToMl();
await ml.navigation.navigateToDataFrameAnalytics();
});
it('loads the job creation flyout', async () => {
await ml.dataFrameAnalytics.startAnalyticsCreation();
});
it('selects the job type', async () => {
await ml.dataFrameAnalyticsCreation.assertJobTypeSelectExists();
await ml.dataFrameAnalyticsCreation.selectJobType(testData.jobType);
});
it('inputs the job id', async () => {
await ml.dataFrameAnalyticsCreation.assertJobIdInputExists();
await ml.dataFrameAnalyticsCreation.setJobId(testData.jobId);
});
it('inputs the job description', async () => {
await ml.dataFrameAnalyticsCreation.assertJobDescriptionInputExists();
await ml.dataFrameAnalyticsCreation.setJobDescription(testData.jobDescription);
});
it('selects the source index', async () => {
await ml.dataFrameAnalyticsCreation.assertSourceIndexInputExists();
await ml.dataFrameAnalyticsCreation.selectSourceIndex(testData.source);
});
it('inputs the destination index', async () => {
await ml.dataFrameAnalyticsCreation.assertDestIndexInputExists();
await ml.dataFrameAnalyticsCreation.setDestIndex(testData.destinationIndex);
});
it('inputs the dependent variable', async () => {
await ml.dataFrameAnalyticsCreation.assertDependentVariableInputExists();
await ml.dataFrameAnalyticsCreation.selectDependentVariable(testData.dependentVariable);
});
it('inputs the training percent', async () => {
await ml.dataFrameAnalyticsCreation.assertTrainingPercentInputExists();
await ml.dataFrameAnalyticsCreation.setTrainingPercent(testData.trainingPercent);
});
it('inputs the model memory limit', async () => {
await ml.dataFrameAnalyticsCreation.assertModelMemoryInputExists();
await ml.dataFrameAnalyticsCreation.setModelMemory(testData.modelMemory);
});
it('sets the create index pattern switch', async () => {
await ml.dataFrameAnalyticsCreation.assertCreateIndexPatternSwitchExists();
await ml.dataFrameAnalyticsCreation.setCreateIndexPatternSwitchState(
testData.createIndexPattern
);
});
it('creates the analytics job', async () => {
await ml.dataFrameAnalyticsCreation.assertCreateButtonExists();
await ml.dataFrameAnalyticsCreation.createAnalyticsJob();
});
it('starts the analytics job', async () => {
await ml.dataFrameAnalyticsCreation.assertStartButtonExists();
await ml.dataFrameAnalyticsCreation.startAnalyticsJob();
});
it('closes the create job flyout', async () => {
await ml.dataFrameAnalyticsCreation.assertCloseButtonExists();
await ml.dataFrameAnalyticsCreation.closeCreateAnalyticsJobFlyout();
});
it('finishes analytics processing', async () => {
await ml.dataFrameAnalytics.waitForAnalyticsCompletion(testData.jobId);
});
it('displays the analytics table', async () => {
await ml.dataFrameAnalytics.assertAnalyticsTableExists();
});
it('displays the stats bar', async () => {
await ml.dataFrameAnalytics.assertAnalyticsStatsBarExists();
});
it('displays the created job in the analytics table', async () => {
await ml.dataFrameAnalyticsTable.refreshAnalyticsTable();
await ml.dataFrameAnalyticsTable.filterWithSearchString(testData.jobId);
const rows = await ml.dataFrameAnalyticsTable.parseAnalyticsTable();
const filteredRows = rows.filter(row => row.id === testData.jobId);
expect(filteredRows).to.have.length(
1,
`Filtered analytics table should have 1 row for job id '${testData.jobId}' (got matching items '${filteredRows}')`
);
});
it('displays details for the created job in the analytics table', async () => {
await ml.dataFrameAnalyticsTable.assertAnalyticsRowFields(testData.jobId, {
id: testData.jobId,
description: testData.jobDescription,
sourceIndex: testData.source,
destinationIndex: testData.destinationIndex,
type: testData.expected.row.type,
status: testData.expected.row.status,
progress: testData.expected.row.progress,
});
});
it('creates the destination index and writes results to it', async () => {
await ml.api.assertIndicesExist(testData.destinationIndex);
await ml.api.assertIndicesNotEmpty(testData.destinationIndex);
});
it('displays the results view for created job', async () => {
await ml.dataFrameAnalyticsTable.openResultsView();
await ml.dataFrameAnalytics.assertClassificationEvaluatePanelElementsExists();
await ml.dataFrameAnalytics.assertClassificationTablePanelExists();
});
});
}
});
}

View file

@ -11,5 +11,6 @@ export default function({ loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./outlier_detection_creation'));
loadTestFile(require.resolve('./regression_creation'));
loadTestFile(require.resolve('./classification_creation'));
});
}

View file

@ -11,7 +11,7 @@ export default function({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const ml = getService('ml');
describe('outlier detection creation', function() {
describe('regression creation', function() {
this.tags(['smoke']);
before(async () => {
await esArchiver.load('ml/egs_regression');

File diff suppressed because it is too large Load diff

View file

@ -44,6 +44,15 @@ export function MachineLearningDataFrameAnalyticsProvider(
await testSubjects.existOrFail('mlDFAnalyticsRegressionExplorationTablePanel');
},
async assertClassificationEvaluatePanelElementsExists() {
await testSubjects.existOrFail('mlDFAnalyticsClassificationExplorationEvaluatePanel');
await testSubjects.existOrFail('mlDFAnalyticsClassificationExplorationConfusionMatrix');
},
async assertClassificationTablePanelExists() {
await testSubjects.existOrFail('mlDFAnalyticsClassificationExplorationTablePanel');
},
async assertOutlierTablePanelExists() {
await testSubjects.existOrFail('mlDFAnalyticsOutlierExplorationTablePanel');
},