pulumi/sdk/nodejs/tests/testmode.spec.ts
Joe Duffy 644d5dc916
Enable unit testing for Pulumi programs (#2638)
* Enable unit testing for Pulumi programs

This change enables rudimentary unit testing of your Pulumi programs, by introducing a `PULUMI_TEST_MODE` envvar that, when set, allows programs to run without a CLI. That includes

* Just being able to import your Pulumi modules, and test ordinary functions -- which otherwise would have often accidentally triggered the "Not Running in a CLI" error message
* Being able to verify a subset of resource properties and shapes, with the caveat that outputs are not included, due to the fact that this is a perpetual "dry run" without any engine operations occurring

In principle, this also means you can attach a debugger and step through your code.

* Finish the unit testing features

This change

1) Incorporates CR feedback, namely requiring that test mode be
   explicitly enabled for any of this to work.

2) Implements Python support for the same capabilities.

3) Includes tests for both JavaScript and Python SDKs.

* Add a note on unit testing to the CHANGELOG

* Use Node 8 friendly assert API

* Embellish the CHANGELOG entry a bit
2019-04-16 22:20:01 -07:00

71 lines
3.1 KiB
TypeScript

// Copyright 2016-2018, Pulumi Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import * as assert from "assert";
import { Output } from "../output";
import { CustomResource } from "../resource";
import * as runtime from "../runtime";
class FakeResource extends CustomResource {
public x?: Output<number>;
constructor(name: string, props?: { x: number }) {
super("nodejs:test:FakeResource", name, props);
}
}
const testModeDisabledError = (err: Error) => {
return err.message === "Program run without the `pulumi` CLI; this may not be what you want " +
"(enable PULUMI_TEST_MODE to disable this error)";
};
describe("testMode", () => {
it("rejects non-test mode", () => {
// Allocating a resource directly while not in test mode errors out.
assert.throws(() => { const _ = new FakeResource("fake"); }, testModeDisabledError);
// Fetching the project name while not in test mode errors out.
assert.throws(() => { const _ = runtime.getProject(); }, testModeDisabledError);
// Fetching the stack name while not in test mode errors out.
assert.throws(() => { const _ = runtime.getStack(); }, testModeDisabledError);
});
it("accepts test mode", () => {
(async () => {
// Set up all the test mode envvars, so that the test will pass.
runtime._setTestModeEnabled(true);
const testProject = "TestProject";
runtime._setProject(testProject);
const testStack = "TestStack";
runtime._setStack(testStack);
try {
// Allocating a resource directly while in test mode succeeds.
let res: FakeResource | undefined;
assert.doesNotThrow(() => { res = new FakeResource("fake", { x: 42 }); });
const x = await new Promise((resolve) => res!.x!.apply(resolve));
assert.equal(x, 42);
// Fetching the project name while in test mode succeeds.
let project: string | undefined;
assert.doesNotThrow(() => { project = runtime.getProject(); });
assert.equal(project, testProject);
// Fetching the stack name while in test mode succeeds.
let stack: string | undefined;
assert.doesNotThrow(() => { stack = runtime.getStack(); });
assert.equal(stack, testStack);
} finally {
runtime._setTestModeEnabled(false);
runtime._setProject("");
runtime._setStack("");
}
})();
});
});