From 50669c5844b7423ed7eb966dd1d2e40036294353 Mon Sep 17 00:00:00 2001
From: Tsuf Cohen <39455181+tsuf239@users.noreply.github.com>
Date: Wed, 2 Aug 2023 18:53:21 +0300
Subject: [PATCH] feat(cli): disable test cleanup with a `--no-clean` flag
(#3646)
## Description
fixes #2884
## 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)*.
---
apps/wing/src/cli.ts | 1 +
apps/wing/src/commands/test.ts | 48 +++++++++++++++++++++++--------
docs/docs/02-concepts/04-tests.md | 44 +++++++++++++++++++++-------
3 files changed, 71 insertions(+), 22 deletions(-)
diff --git a/apps/wing/src/cli.ts b/apps/wing/src/cli.ts
index 3d8c68a8094..8858d658ca7 100644
--- a/apps/wing/src/cli.ts
+++ b/apps/wing/src/cli.ts
@@ -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"));
diff --git a/apps/wing/src/commands/test.ts b/apps/wing/src/commands/test.ts
index fe6776e3922..efc38b01dab 100644
--- a/apps/wing/src/commands/test.ts
+++ b/apps/wing/src/commands/test.ts
@@ -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";
@@ -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 {
const startTime = Date.now();
@@ -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}...`,
() =>
@@ -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}`);
}
@@ -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;
@@ -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 {
+async function testAwsCdk(synthDir: string, options: TestOptions): Promise {
+ const { clean } = options;
try {
isAwsCdkInstalled(synthDir);
@@ -301,7 +316,11 @@ async function testAwsCdk(synthDir: string): Promise {
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);
+ }
}
}
@@ -339,7 +358,8 @@ async function awsCdkOutput(synthDir: string, name: string, stackName: string) {
return parsed[stackName][name];
}
-async function testTfAws(synthDir: string): Promise {
+async function testTfAws(synthDir: string, options: TestOptions): Promise {
+ const { clean } = options;
try {
if (!isTerraformInstalled(synthDir)) {
throw new Error(
@@ -382,7 +402,11 @@ async function testTfAws(synthDir: string): Promise {
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);
+ }
}
}
diff --git a/docs/docs/02-concepts/04-tests.md b/docs/docs/02-concepts/04-tests.md
index 59e0239e8f3..7bd3b4121c6 100644
--- a/docs/docs/02-concepts/04-tests.md
+++ b/docs/docs/02-concepts/04-tests.md
@@ -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 code
+ // test code
}
```
+
If a test throws an exception (typically using the `assert` function), it's considered to have failed.
Here's an example:
@@ -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
@@ -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
@@ -92,9 +97,10 @@ 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
@@ -102,8 +108,27 @@ Running the test on the tf-aws target
✔ 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
@@ -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;
@@ -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)
-
-