Skip to content

Commit aa6ac00

Browse files
committed
Added new properties to Test proto
1 parent e168207 commit aa6ac00

File tree

3 files changed

+222
-7
lines changed

3 files changed

+222
-7
lines changed

core/actions/test.ts

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { verifyObjectMatchesProto, VerifyProtoErrorBehaviour } from "df/common/protos";
22
import { ActionBuilder, INamedConfig, TableType } from "df/core/actions";
33
import { IncrementalTable } from "df/core/actions/incremental_table";
4-
import { Table } from "df/core/actions/table";
5-
import { View } from "df/core/actions/view";
4+
import { Table, TableContext } from "df/core/actions/table";
5+
import { View, ViewContext } from "df/core/actions/view";
66
import { Contextable, IActionContext, ITableContext, Resolvable } from "df/core/contextables";
77
import { Session } from "df/core/session";
88
import { targetStringifier } from "df/core/targets";
@@ -77,7 +77,8 @@ export class Test extends ActionBuilder<dataform.Test> {
7777

7878
/** @hidden We delay contextification until the final compile step, so hold these here for now. */
7979
public contextableInputs = new Map<string, Contextable<IActionContext, string>>();
80-
private contextableQuery: Contextable<IActionContext, string>;
80+
private inputToTargets = new Map<string, dataform.Target>();
81+
private contextableQuery: Contextable<IActionContext, string>;
8182
private datasetToTest: Resolvable;
8283

8384
/**
@@ -127,13 +128,20 @@ export class Test extends ActionBuilder<dataform.Test> {
127128
* Sets the input query to unit test against.
128129
*/
129130
public input(refName: string | string[], contextableQuery: Contextable<IActionContext, string>) {
131+
const target = resolvableAsTarget(toResolvable(refName));
132+
const inputName = targetStringifier.stringify(target);
130133
this.contextableInputs.set(
131-
targetStringifier.stringify(resolvableAsTarget(toResolvable(refName))),
134+
inputName,
132135
contextableQuery
133136
);
137+
this.inputToTargets.set(inputName, target);
134138
return this;
135139
}
136140

141+
public resolveSchema(resolveSchema: boolean) {
142+
this.proto.resolveSchema = resolveSchema;
143+
}
144+
137145
/**
138146
* Sets the expected output of the query to being tested against.
139147
*/
@@ -188,7 +196,34 @@ export class Test extends ActionBuilder<dataform.Test> {
188196
} else {
189197
const refReplacingContext = new RefReplacingContext(testContext);
190198
this.proto.testQuery = refReplacingContext.apply(dataset.contextableQuery);
199+
200+
// Set the test query with the fully qualified table references.
201+
if (dataset instanceof Table) {
202+
const tableContext = new TableContext(dataset);
203+
this.proto.query = tableContext.apply(dataset.contextableQuery);
204+
} else {
205+
const viewContext = new ViewContext(dataset);
206+
this.proto.query = viewContext.apply(dataset.contextableQuery);
207+
}
191208
}
209+
210+
// Build the inputs list with the fully qualified input names and the input query to mock each input.
211+
this.contextableInputs.forEach((inputContextable, inputName) => {
212+
const testInput = dataform.Test.TestInput.create();
213+
testInput.query = testContext.apply(inputContextable);
214+
testInput.target = this.applySessionToTarget(
215+
this.inputToTargets.get(inputName),
216+
this.session.projectConfig,
217+
this.getFileName(),
218+
{
219+
validateTarget: true
220+
});
221+
this.proto.inputs.push(testInput);
222+
});
223+
224+
// Add target property/
225+
this.proto.testTarget = dataset.getTarget();
226+
this.proto.resolveSchema = false;
192227
}
193228
this.proto.expectedOutputQuery = testContext.apply(this.contextableQuery);
194229

core/actions/test_test.ts

Lines changed: 173 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,175 @@
1-
import { suite } from "df/testing";
1+
import { expect } from "chai";
2+
import * as fs from "fs-extra";
3+
import * as path from "path";
24

3-
suite("test", () => {
4-
// This action currently has no unit tests!
5+
import { asPlainObject, suite, test } from "df/testing";
6+
import { TmpDirFixture } from "df/testing/fixtures";
7+
import {
8+
coreExecutionRequestFromPath,
9+
runMainInVm,
10+
VALID_WORKFLOW_SETTINGS_YAML
11+
} from "df/testing/run_core";
12+
13+
suite("test", ({ afterEach }) => {
14+
const tmpDirFixture = new TmpDirFixture(afterEach);
15+
16+
test(`test with no inputs`, () => {
17+
const projectDir = tmpDirFixture.createNewTmpDir();
18+
const workflowSettingsPath = path.join(projectDir, "workflow_settings.yaml");
19+
const definitionsDir = path.join(projectDir, "definitions");
20+
const actionsYamlPath = path.join(definitionsDir, "actions.yaml");
21+
const actionSqlPath = path.join(definitionsDir, "action.sql");
22+
const actionTestSqlxPath = path.join(definitionsDir, "action_test.sqlx");
23+
24+
fs.writeFileSync(workflowSettingsPath, VALID_WORKFLOW_SETTINGS_YAML);
25+
fs.mkdirSync(definitionsDir);
26+
fs.writeFileSync(actionsYamlPath, `
27+
actions:
28+
- table:
29+
filename: action.sql`
30+
);
31+
fs.writeFileSync(actionSqlPath, "SELECT 1");
32+
fs.writeFileSync(actionTestSqlxPath, `
33+
config {
34+
type: "test",
35+
dataset: "action"
36+
}
37+
SELECT 1`);
38+
39+
const result = runMainInVm(coreExecutionRequestFromPath(projectDir));
40+
41+
expect(result.compile.compiledGraph.graphErrors.compilationErrors).deep.equals([]);
42+
expect(asPlainObject(result.compile.compiledGraph.tests)).deep.equals(
43+
asPlainObject([
44+
{
45+
// Original test properties
46+
name: "action_test",
47+
testQuery: "SELECT 1",
48+
expectedOutputQuery: "\n\nSELECT 1",
49+
fileName: "definitions/action_test.sqlx",
50+
51+
// New properties
52+
testTarget: {
53+
database: "defaultProject",
54+
schema: "defaultDataset",
55+
name: "action"
56+
},
57+
query: "SELECT 1",
58+
resolveSchema: false,
59+
}
60+
])
61+
);
62+
});
63+
64+
test(`test with multiple_inputs input`, () => {
65+
const projectDir = tmpDirFixture.createNewTmpDir();
66+
const workflowSettingsPath = path.join(projectDir, "workflow_settings.yaml");
67+
const definitionsDir = path.join(projectDir, "definitions");
68+
const actionsYamlPath = path.join(definitionsDir, "actions.yaml");
69+
const action1SqlxPath = path.join(definitionsDir, "action1.sqlx");
70+
const action1TestSqlxPath = path.join(definitionsDir, "action1_test.sqlx");
71+
const action2SqlxPath = path.join(definitionsDir, "action2.sqlx");
72+
const action2TestSqlxPath = path.join(definitionsDir, "action2_test.sqlx");
73+
74+
fs.writeFileSync(workflowSettingsPath, VALID_WORKFLOW_SETTINGS_YAML);
75+
fs.mkdirSync(definitionsDir);
76+
77+
// Add a declaration
78+
fs.writeFileSync(actionsYamlPath, `
79+
actions:
80+
- declaration:
81+
name: a_declaration`
82+
);
83+
84+
// Add an action with a test, reads from declaration
85+
fs.writeFileSync(action1SqlxPath, `
86+
config {
87+
type: "table",
88+
}
89+
SELECT a,b,c FROM \${ref("a_declaration")}
90+
`);
91+
fs.writeFileSync(action1TestSqlxPath, `
92+
config {
93+
type: "test",
94+
dataset: "action1"
95+
}
96+
input "a_declaration" {
97+
SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS d
98+
}
99+
SELECT 1 AS a, 2 AS b, 3 AS c`);
100+
101+
102+
// Add an action with a test, reads from previous action
103+
fs.writeFileSync(action2SqlxPath, `
104+
config {
105+
type: "table",
106+
}
107+
SELECT a,b FROM \${ref("action1")}
108+
`);
109+
fs.writeFileSync(action2TestSqlxPath, `
110+
config {
111+
type: "test",
112+
dataset: "action2"
113+
}
114+
input "action1" {
115+
SELECT 1 AS a, 2 AS b, 3 AS c
116+
}
117+
SELECT 1 AS a, 2 AS b`);
118+
119+
const result = runMainInVm(coreExecutionRequestFromPath(projectDir));
120+
121+
expect(result.compile.compiledGraph.graphErrors.compilationErrors).deep.equals([]);
122+
expect(asPlainObject(result.compile.compiledGraph.tests)).deep.equals(
123+
asPlainObject([
124+
{
125+
// Original test properties
126+
name: "action1_test",
127+
testQuery: "\n\nSELECT a,b,c FROM (\n SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS d\n)\n ",
128+
expectedOutputQuery: "\n\n\nSELECT 1 AS a, 2 AS b, 3 AS c",
129+
fileName: "definitions/action1_test.sqlx",
130+
131+
// New properties
132+
testTarget: {
133+
database: "defaultProject",
134+
schema: "defaultDataset",
135+
name: "action1"
136+
},
137+
inputs: [{
138+
query: "\n SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS d\n",
139+
target: {
140+
database: "defaultProject",
141+
schema: "defaultDataset",
142+
name: "a_declaration"
143+
}
144+
}],
145+
query: "\n\nSELECT a,b,c FROM `defaultProject.defaultDataset.a_declaration`\n ",
146+
resolveSchema: false,
147+
},
148+
{
149+
// Original test properties
150+
name: "action2_test",
151+
testQuery: "\n\nSELECT a,b FROM (\n SELECT 1 AS a, 2 AS b, 3 AS c\n)\n ",
152+
expectedOutputQuery: "\n\n\nSELECT 1 AS a, 2 AS b",
153+
fileName: "definitions/action2_test.sqlx",
154+
155+
// New properties
156+
testTarget: {
157+
database: "defaultProject",
158+
schema: "defaultDataset",
159+
name: "action2"
160+
},
161+
inputs: [{
162+
query: "\n SELECT 1 AS a, 2 AS b, 3 AS c\n",
163+
target: {
164+
database: "defaultProject",
165+
schema: "defaultDataset",
166+
name: "action1"
167+
}
168+
}],
169+
query: "\n\nSELECT a,b FROM `defaultProject.defaultDataset.action1`\n ",
170+
resolveSchema: false,
171+
}
172+
])
173+
);
174+
});
5175
});

protos/core.proto

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,16 @@ message Test {
264264

265265
// Generated.
266266
string file_name = 4;
267+
268+
Target test_target = 5;
269+
repeated TestInput inputs = 6;
270+
string query = 7;
271+
bool resolve_schema = 8;
272+
273+
message TestInput {
274+
Target target = 1;
275+
string query = 2;
276+
}
267277
}
268278

269279
message Notebook {

0 commit comments

Comments
 (0)