Skip to content

chore: add e2e test #51

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ start_unit_test(
.then((success) => {
if (!success) {
console.error(chalk.redBright("Test Failed") + "\n");
exit(-1);
exit(255);
}
})
.catch((e) => {
console.error(chalk.redBright(" Test crash, error message: ") + chalk.yellowBright(`${e.stack}`) + "\n");
exit(-1);
exit(255);
});
49 changes: 49 additions & 0 deletions docs/api-documents/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,52 @@ module.exports = {
// mode: ["html", "json", "table"],
};
```

### Imports

```typescript
export interface ImportsArgument {
module: WebAssembly.Module;
instance: WebAssembly.Instance;
exports: (ASUtil & Record<string, unknown>);
framework: UnitTestFramework;
}
export abstract class UnitTestFramework {
/**
* function to redirect log message to unittest framework
* @param msg: message to log
*/
abstract log(msg: string): void;
}
```

There are 2 useful fields.

- `exports`: contains exported function from test cases and [AS help API](https://github.com/AssemblyScript/assemblyscript/blob/3defefd5b09248d697a2e6bd1e7201c0cf98def1/lib/loader/index.d.ts#L23).
- `framework`: contains runtime provided function.

- `log`: redirect log message from test cases to unittest framework. It will be showed in failed info.
::: details

```typescript
test("failed test", () => {
log("This is a log message for the failed test."); // log to be redirect
expect(1 + 1).equal(3);
});

test("succeed test", () => {
log("This is a log message for the succeed test."); // log to be redirect
expect(1 + 1).equal(2);
});
```

will output

```
Error Message:
failed test:
*.test.ts:6:2 value: 2 expect: = 3
This is a log message for the failed test. <- only log in failed test will be showed here
```

:::
17 changes: 14 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
},
"prettier": "@schleifner/prettier-config",
"scripts": {
"watch:ts": "tsc --build ./src/tsconfig.json --watch",
"build": "node scripts/build_instrumentation.js -j 2 && tsc --build ./transform/tsconfig.json && tsc --build ./src/tsconfig.json",
"test:as": "node bin/as-test.js",
"test:ts": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
"test:cpp": "cmake -B build -S . && cmake --build build --parallel 2 --target wasm-instrumentation-test wasm-opt && build/bin/wasm-instrumentation-test",
"test": "npm run test:as && npm run test:ts && npm run test:cpp",
"test:e2e": " node tests/e2e/run.js",
"test": "npm run test:as && npm run test:ts && npm run test:cpp && npm run test:e2e",
"lint:ts": "eslint src transform tests/ts/test --max-warnings=0",
"lint:as": "npx eslint --config ./assembly/eslint.config.mjs assembly --max-warnings=0",
"lint": "npm run lint:ts && prettier -c .",
Expand Down Expand Up @@ -48,6 +50,7 @@
"@types/node": "^22.0.0",
"assemblyscript-prettier": "^3.0.1",
"cross-env": "^7.0.3",
"diff": "^8.0.2",
"jest": "^29.5.0",
"prettier": "^3.0.0",
"ts-jest": "^29.1.0",
Expand Down
8 changes: 4 additions & 4 deletions src/executionResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ export class ExecutionResult {
for (const msg of value) {
const [index, actualValue, expectValue] = msg;
const debugLocation = expectInfo.get(index);
let errorMsg = `${debugLocation ?? ""}\tvalue: ${actualValue}\texpect: ${expectValue}`;
let errorMsg = `${debugLocation ?? ""} value: ${actualValue} expect: ${expectValue}`;
if (errorMsg.length > 160) {
errorMsg = `${debugLocation ?? ""}\nvalue: \n\t${actualValue}\nexpect: \n\t${expectValue}`;
errorMsg = `${debugLocation ?? ""}\nvalue: \n ${actualValue}\nexpect: \n ${expectValue}`;
}
errorMsgs.push(errorMsg);
}
Expand All @@ -52,9 +52,9 @@ export class ExecutionResult {
if (this.fail !== 0) {
log(chalk.red("Error Message: "));
for (const [testcaseName, { assertMessages, logMessages }] of this.failedInfos.entries()) {
log(`\t${testcaseName}: `);
log(` ${testcaseName}: `);
for (const assertMessage of assertMessages) {
log("\t\t" + chalk.yellow(assertMessage));
log(" " + chalk.yellow(assertMessage));
}
for (const logMessage of logMessages ?? []) {
log(chalk.gray(logMessage));
Expand Down
20 changes: 20 additions & 0 deletions tests/e2e/printLogInFailedInfo/as-test.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import os from "node:os";
import path from "node:path";

const tmpFolder = path.join(os.tmpdir(), "as-test-e2e");

export default {
include: ["tests/e2e/printLogInFailedInfo"],
imports(runtime) {
return {
env: {
log: (msg) => {
runtime.framework.log(runtime.exports.__getString(msg));
},
},
};
},
temp: tmpFolder,
output: tmpFolder,
mode: [],
};
1 change: 1 addition & 0 deletions tests/e2e/printLogInFailedInfo/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export declare function log(msg: string): void;
12 changes: 12 additions & 0 deletions tests/e2e/printLogInFailedInfo/source.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { test, expect } from "../../../assembly";
import { log } from "./env";

test("failed test", () => {
log("This is a log message for the failed test.");
expect(1 + 1).equal(3);
});

test("succeed test", () => {
log("This is a log message for the succeed test.");
expect(1 + 1).equal(2);
});
4 changes: 4 additions & 0 deletions tests/e2e/printLogInFailedInfo/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "assemblyscript/std/assembly.json",
"include": ["./**/*.ts"]
}
42 changes: 42 additions & 0 deletions tests/e2e/run.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import assert from "node:assert";
import { exec } from "node:child_process";
import { diffChars } from "diff";
import chalk from "chalk";

function assertStringEq(s1, s2) {
const parts = diffChars(s1, s2);
const diffs = [];
let hasDiff = false;
for (const part of parts) {
if (part.added) {
hasDiff = true;
diffs.push(chalk.bgGreen(part.value));
} else if (part.removed) {
hasDiff = true;
diffs.push(chalk.bgRed(part.value));
} else {
diffs.push(part.value);
}
}
assert(!hasDiff, diffs.join(""));
}

console.log("Running e2e test: printLogInFailedInfo");
exec("node ./bin/as-test.js --config tests/e2e/printLogInFailedInfo/as-test.config.js", (error, stdout, stderr) => {
assert(error.code === 255);
const expectStdOut = `
code analysis: OK
compile testcases: OK
instrument: OK
execute testcases: OK

test case: 1/2 (success/total)

Error Message:
failed test:
tests/e2e/printLogInFailedInfo/source.test.ts:6:2 value: 2 expect: = 3
This is a log message for the failed test.
`.trimStart();

assertStringEq(expectStdOut, stdout);
});
8 changes: 4 additions & 4 deletions tests/ts/test/__snapshots__/executionResult.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ exports[`print 1`] = `
test case: 27/28 (success/total)

Error Message:
A:
tests/as/comparison.test.ts:10:20 value: 100 expect: = 200
A:
tests/as/comparison.test.ts:10:20 value: 100 expect: = 200
log message 1
log message 2
log message 3"
Expand All @@ -17,8 +17,8 @@ exports[`print 2`] = `
test case: 27/28 (success/total)

Error Message: 
A:
tests/as/comparison.test.ts:10:20 value: 100 expect: = 200
A:
tests/as/comparison.test.ts:10:20 value: 100 expect: = 200
log message 1
log message 2
log message 3"
Expand Down
8 changes: 4 additions & 4 deletions tests/ts/test/executionResult.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ test("equal failed", async () => {
const expectFailedInfo: FailedInfoMap = new Map();
expectFailedInfo.set("A", {
assertMessages: [
"tests/as/comparison.test.ts:10:20\tvalue: 100\texpect: = 200",
"tests/as/comparison.test.ts:15:27\tvalue: [10]\texpect: = [1]",
"tests/as/comparison.test.ts:59:22\tvalue: { 1 : 1.5, 2 : 2.5 }\texpect: = { 1: 1.5, 2 : 2.0 }",
`tests/as/comparison.test.ts:48:47\nvalue: \n\t${actualString}\nexpect: \n\t${expectString}`,
"tests/as/comparison.test.ts:10:20 value: 100 expect: = 200",
"tests/as/comparison.test.ts:15:27 value: [10] expect: = [1]",
"tests/as/comparison.test.ts:59:22 value: { 1 : 1.5, 2 : 2.5 } expect: = { 1: 1.5, 2 : 2.0 }",
`tests/as/comparison.test.ts:48:47\nvalue: \n ${actualString}\nexpect: \n ${expectString}`,
],
logMessages: ["log message 1", "log message 2", "log message 3"],
});
Expand Down