Skip to content

Commit

Permalink
feat(cli): disable test cleanup with a --no-clean flag (#3646)
Browse files Browse the repository at this point in the history
## Description
fixes #2884

<img width="881" alt="image" src="https://github.com/winglang/wing/assets/39455181/e655e4fe-aea7-4bb8-9ae0-80035ae0f08e">



## Checklist

- [x] Title matches [Winglang's style guide](https://www.winglang.io/contributing/start-here/pull_requests#how-are-pull-request-titles-formatted)
- [x] Description explains motivation and solution
- [ ] Tests added (always). - *tested manually all targets*
- [x] Docs updated (only required for features)
- [x] Added `pr/e2e-full` label if this feature requires end-to-end testing

*By submitting this pull request, I confirm that my contribution is made under the terms of the [Wing Cloud Contribution License](https://github.com/winglang/wing/blob/main/CONTRIBUTION_LICENSE.md)*.
  • Loading branch information
tsuf239 authored Aug 2, 2023
1 parent a561686 commit 50669c5
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 22 deletions.
1 change: 1 addition & 0 deletions apps/wing/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ async function main() {
.default("sim")
)
.option("-p, --plugins [plugin...]", "Compiler plugins")
.option("--no-clean", "Keep build output")
.hook("preAction", progressHook)
.hook("preAction", collectAnalyticsHook)
.action(runSubCommand("test"));
Expand Down
48 changes: 36 additions & 12 deletions apps/wing/src/commands/test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { basename, sep } from "path";
import { basename, resolve, sep } from "path";
import { compile, CompileOptions } from "./compile";
import chalk from "chalk";
import { std, testing } from "@winglang/sdk";
Expand All @@ -23,7 +23,9 @@ const generateTestName = (path: string) => path.split(sep).slice(-2).join("/");
/**
* Options for the `test` command.
*/
export interface TestOptions extends CompileOptions {}
export interface TestOptions extends CompileOptions {
clean: boolean;
}

export async function test(entrypoints: string[], options: TestOptions): Promise<number> {
const startTime = Date.now();
Expand Down Expand Up @@ -129,7 +131,8 @@ function printResults(
async function testOne(entrypoint: string, options: TestOptions) {
// since the test cleans up after each run, it's essential to create a temporary directory-
// at least one that is different then the usual compilation dir, otherwise we might end up cleaning up the user's actual resources.
const tempFile: string = Target.SIM ? entrypoint : await generateTmpDir(entrypoint);
const tempFile: string =
options.target === Target.SIM ? entrypoint : await generateTmpDir(entrypoint);
const synthDir = await withSpinner(
`Compiling ${generateTestName(entrypoint)} to ${options.target}...`,
() =>
Expand All @@ -141,11 +144,11 @@ async function testOne(entrypoint: string, options: TestOptions) {

switch (options.target) {
case Target.SIM:
return await testSimulator(synthDir);
return await testSimulator(synthDir, options);
case Target.TF_AWS:
return await testTfAws(synthDir);
return await testTfAws(synthDir, options);
case Target.AWSCDK:
return await testAwsCdk(synthDir);
return await testAwsCdk(synthDir, options);
default:
throw new Error(`unsupported target ${options.target}`);
}
Expand Down Expand Up @@ -235,8 +238,15 @@ function testResultsContainsFailure(results: std.TestResult[]): boolean {
return results.some((r) => !r.pass);
}

async function testSimulator(synthDir: string) {
function noCleanUp(synthDir: string) {
console.log(
chalk.yellowBright.bold(`Cleanup is disabled!\nOutput files available at ${resolve(synthDir)}`)
);
}

async function testSimulator(synthDir: string, options: TestOptions) {
const s = new testing.Simulator({ simfile: synthDir });
const { clean } = options;
await s.start();

const testRunner = s.getResource("root/cloud.TestRunner") as std.ITestRunnerClient;
Expand All @@ -254,12 +264,17 @@ async function testSimulator(synthDir: string) {
const testReport = renderTestReport(synthDir, results);
console.log(testReport);

rmSync(synthDir, { recursive: true, force: true });
if (clean) {
rmSync(synthDir, { recursive: true, force: true });
} else {
noCleanUp(synthDir);
}

return results;
}

async function testAwsCdk(synthDir: string): Promise<std.TestResult[]> {
async function testAwsCdk(synthDir: string, options: TestOptions): Promise<std.TestResult[]> {
const { clean } = options;
try {
isAwsCdkInstalled(synthDir);

Expand Down Expand Up @@ -301,7 +316,11 @@ async function testAwsCdk(synthDir: string): Promise<std.TestResult[]> {
console.warn((err as Error).message);
return [{ pass: false, path: "", error: (err as Error).message, traces: [] }];
} finally {
await cleanupCdk(synthDir);
if (clean) {
await cleanupCdk(synthDir);
} else {
noCleanUp(synthDir);
}
}
}

Expand Down Expand Up @@ -339,7 +358,8 @@ async function awsCdkOutput(synthDir: string, name: string, stackName: string) {
return parsed[stackName][name];
}

async function testTfAws(synthDir: string): Promise<std.TestResult[] | void> {
async function testTfAws(synthDir: string, options: TestOptions): Promise<std.TestResult[] | void> {
const { clean } = options;
try {
if (!isTerraformInstalled(synthDir)) {
throw new Error(
Expand Down Expand Up @@ -382,7 +402,11 @@ async function testTfAws(synthDir: string): Promise<std.TestResult[] | void> {
console.warn((err as Error).message);
return [{ pass: false, path: "", error: (err as Error).message, traces: [] }];
} finally {
await cleanupTf(synthDir);
if (clean) {
await cleanupTf(synthDir);
} else {
noCleanUp(synthDir);
}
}
}

Expand Down
44 changes: 34 additions & 10 deletions docs/docs/02-concepts/04-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ keywords: [Wing test, multi-cloud]
Winglang incorporates a lightweight testing framework, which is built around the `wing test` command and the `test` keyword. It lets you to run the same tests, in isolation, on both the Wing simulator and in the cloud.

### How to create a test

You can create a test by adding the following code structure to any Winglang file (.w):

```ts wing
test "<test-name>" {
// test code
// test code
}
```

If a test throws an exception (typically using the `assert` function), it's considered to have failed.

Here's an example:
Expand All @@ -28,13 +31,14 @@ test "abs" {
```

### Running tests in the Simulator

You can execute all tests in a `.w` file in the simulator using the following command:

```sh
% wing test example.w --target sim
% wing test example.w --target sim
pass ─ example.wsim » root/env0/test:abs


Tests 1 passed (1)
Test Files 1 passed (1)
Duration 0m0.54s
Expand All @@ -43,6 +47,7 @@ Duration 0m0.54s
**Notice:** The `--target sim` argument can be omitted as it's the default target for the wing test command.

### Tests run in isolation

Every Winglang test is executed in complete isolation. Take a look at the following code:

```ts playground
Expand Down Expand Up @@ -92,18 +97,38 @@ test "bucket onCreate" {

```

Running the test on the tf-aws target
Running the test on the tf-aws target

```sh
% wing test example.w -t tf-aws
% wing test example.w -t tf-aws
✔ Compiling example.w to tf-aws...
✔ terraform init
✔ terraform apply
✔ Setting up test runner...
✔ Running tests...
pass ─ example.tfaws » root/Default/env0/test:bucket onCreate
✔ terraform destroy




Tests 1 passed (1)
Test Files 1 passed (1)
Duration 1m31.44s
```

By default, the tested resources will be destroyed at the end of the test. You can use the `--no-clean` to keep them up. The path to the randomized directory containing the output files will be displayed at the end of the test.

```sh
% wing test example.w -t tf-aws --no-clean
✔ Compiling example.w to tf-aws...
✔ terraform init
✔ terraform apply
✔ Setting up test runner...
✔ Running tests...
pass ─ example.tfaws » root/Default/env0/test:bucket onCreate
✔ terraform destroy
Clean up is disabled!
Output files available at /var/folders/1m/..../example.tfaws

Tests 1 passed (1)
Test Files 1 passed (1)
Duration 1m31.44s
Expand All @@ -113,7 +138,8 @@ Duration 1m31.44s

Wing Console provides a straightforward method to run either a single test or all your tests.

Consider the following code:
Consider the following code:

```ts playground
// example.w
bring cloud;
Expand All @@ -138,5 +164,3 @@ test "this test should fail" {

Refer to the TESTS section in the image below. You have the option to run all tests or a single test.
![image](https://github.com/winglang/wing/assets/1727147/7d5ebc00-9316-41d1-9a3c-0e28e195d077)


0 comments on commit 50669c5

Please sign in to comment.