Skip to content
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
46 changes: 46 additions & 0 deletions .github/workflows/gh-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages

on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false

jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run docs:build

- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: docs/.vitepress/dist
- id: deployment
uses: actions/deploy-pages@v4
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@
/coverage-ts

/tests/cpp/lit/build

/docs/.vitepress/dist
/docs/.vitepress/cache
246 changes: 0 additions & 246 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,252 +21,6 @@ A comprehensive AssemblyScript testing solution, offering developers a robust su
- Coverage statistics
- Expectations

## Getting Started

Install Assemblyscript Unittest Framework using npm

```bash
npm install --save-dev assemblyscript-unittest-framework
```

Let's get started by writing a test for a simple function that add two numbers. Assume that there is already environment of assemblyscript.

First, create `source/sum.ts`:

```Typescript
export function add(a: i32, b: i32): i32 {
return a + b;
}
```

Then, create a file named `tests/sum.test.ts`. This will contain our actual test:

```Typescript
import { test, expect, endTest } from "assemblyscript-unittest-framework/assembly";
import { add } from "../source/sum";

test("sum", () => {
expect(add(1, 2)).equal(3);
expect(add(1, 1)).equal(3);
});
endTest(); // Don't forget it!
```

**Don't forget `endTest()` at the end of `*.test.ts` files**

Create a config file in project root `as-test.config.js`:

for cjs:

```javascript
module.exports = {
include: ["source", "tests"],
};
```

for mjs:

```javascript
export default {
include: ["source", "tests"],
};
```

Add the following section to your `package.json`

```json
{
"scripts": {
"test": "as-test"
}
}
```

Finally, run `npm run test` and as-test will print this message:

```
transform source/sum.ts => build/source/sum.ts.cov
transform build/source/sum.ts.cov => build/source/sum.ts
transform tests/sum.test.ts => build/tests/sum.test.ts
(node:489815) ExperimentalWarning: WASI is an experimental feature. This feature could change at any time

test case: 1/2 (success/total)

Error Message:
sum:
tests/sum.test.ts:6:3 (6:3, 6:29)
```

You can also use `npx as-test -h` for more information to control detail configurations

## Configuration

This is the template of `as-test.config.js`:

```javascript
module.exports = {
// test related code folder
include: ["source", "tests"],
exclude: [],

/** optional: assemblyscript compile flag, default is --exportStart _start -O0 */
flags: "",

/**
* optional: import functions
* @param {ImportsArgument} runtime
* @returns
*/
imports(runtime) {
return {
env: {
logInfo(ptr, len) {
if (runtime.exports) {
let arrbuf = runtime.exports.__getArrayBuffer(ptr);
let str = Buffer.from(arrbuf).toString("utf8");
console.log(str);
}
},
},
builtin: {
getU8FromLinkedMemory(a) {
return 1;
},
},
};
},

/** optional: template file path, default "coverage" */
// temp: "coverage",

/** optional: report file path, default "coverage" */
// output: "coverage",

/** optional: test result output format, default "table" */
// mode: ["html", "json", "table"],
};

```

## Using Matchers

The simplest way to test a value is with exact equality.

```typescript
test('two plus two is four', () => {
expect(2 + 2).equal(4);
});
```

In this code, `expect(2+2)` returns an "Value" object. You typically won't do much with these objects except call matchers on them. In this code, `.equal(4)` is the matcher. When Jest runs, it tracks all the failing matchers so that it can print out nice error messages for you.

### Equal

In the most condition, `equal` is similar as `==`, you can use this matcher to compare `i32 | i64 | u32 | u64 | f32 | f64 | string` just like `==`. What's more, it can also be used to compare some inner type, such as `Array | Map | Set`.

However, **Class** and **Interface** cannot be compared directly now.

`notEqual` is the opposite of `equal`

### Numbers

Most ways of comparing numbers have matcher equivalents, like `equal`, `greaterThan`, `greaterThanOrEqual`, `lessThan`, `lessThanOrEqual`.

Specially, for float type, use `closeTo` instead of `equal` to avoid rounding error.

## Nullable

`isNull` and `notNull` matcher can be used to a nullable object.
Of cource, you can also use `equal` and `notEqual` to do same thing with explicit generic declartion `expect<T | null>()`

## Using Mock Function

Because Assemblyscript's grammar is not as flexible as javascript, mock function have a lot of limitation and API design is not similar as jest (a javascript test framework).

However, There is a way to do some mock function.

Imagine that we are testing a function which includes a system-interface:

```typescript
// source.ts
declare function sys_getTime(): i32;
export function getTime(): bool {
let errno = sys_getTime();
if (errno < 0) {
// error handle
return false;
}
// do something
return true;
}
```

To test error handle part, we need to inject some code to `sys_getTime` and expect to return a errno.

```typescript
// source.test.ts
test("getTime error handle", () => {
const fn = mock(sys_getTime, () => {
return -1;
});
expect(getTime()).equal(false); // success
expect(fn.calls).equal(1); // success
});
endTest();
```

mock API can temporary change the behavior of function, effective scope is each test.
In this mock function, you can do every thing include expecting arguments, mock return values and so on.

Tips:

- Because Assemblyscript is a strongly typed language, you should keep the function signature aligned.
- AssemblyScript does not support closures. If a mock function needs to be called several times in one test, and you want it to return different values or match arguments to different values, using a global counter for this function is a good way to achieve this.

### Example for MockFn

1. expect arguments

```typescript
test("check argument", () => {
const fn = mock(add, (a: i32, b: i32) => {
expect(a).equal(1);
return a + b;
});
expect(fn.calls).greaterThanOrEqual(1);
});
```

2. return difference value

```typescript
const ret = [1,2,3,4,5,6,7,8]; // global variant
const calls = 0; // global variant
test("check argument", () => {
const fn = mock(add, (a: i32, b: i32) => {
return ret[calls++];
});
expect(fn.calls).greaterThanOrEqual(1);
});
```

3. re-call origin

```typescript
test("call origin", () => {
mock(add, (a: i32, b: i32) => {
unmock(add);
const res = add(a,b);
remock(add);
return res;
});
});
```

## Coverage Report

After testing, you can get a html / json / table format test coverage report include "Statements Coverage", "Branches Coverage", "Functions Coverage", "Lines Coverage"

## Architecture

- `assembly/` written in Assemblyscript, provides user-accessible testing APIs such as test, inspect, mock, etc.
Expand Down
43 changes: 43 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { defineConfig } from "vitepress";

// https://vitepress.dev/reference/site-config
export default defineConfig({
title: "assemblyscript unittest framework",
description: "documents of assemblyscript unittest framework",
base: "/assemblyscript-unittest-framework/",
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
search: {
provider: "local",
},
nav: [{ text: "Home", link: "/" }],
sidebar: [
{
text: "Document",
items: [
{ text: "Quick Start", link: "/quick-start.md" },
{
text: "API documents",
link: "/api-documents/index",
items: [
{ text: "Configuration", link: "/api-documents/configuration" },
{ text: "Matchers", link: "/api-documents/matchers" },
{ text: "Mock Function", link: "/api-documents/mock-function" },
{ text: "Report", link: "/api-documents/coverage-report" },
],
},
{
text: "Technical Details",
items: [
{
text: "code debug info between C++ and TS",
link: "/technical-details/code-debug-info",
},
],
},
],
},
],
socialLinks: [{ icon: "github", link: "https://github.com/wasm-ecosystem/assemblyscript-unittest-framework" }],
},
});
48 changes: 48 additions & 0 deletions docs/api-documents/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
## Configuration

This is the template of `as-test.config.js`:

```javascript
module.exports = {
// test related code folder
include: ["source", "tests"],
exclude: [],

/** optional: assemblyscript compile flag, default is --exportStart _start -O0 */
flags: "",

/**
* optional: import functions
* @param {ImportsArgument} runtime
* @returns
*/
imports(runtime) {
return {
env: {
logInfo(ptr, len) {
if (runtime.exports) {
let arrbuf = runtime.exports.__getArrayBuffer(ptr);
let str = Buffer.from(arrbuf).toString("utf8");
console.log(str);
}
},
},
builtin: {
getU8FromLinkedMemory(a) {
return 1;
},
},
};
},

/** optional: template file path, default "coverage" */
// temp: "coverage",

/** optional: report file path, default "coverage" */
// output: "coverage",

/** optional: test result output format, default "table" */
// mode: ["html", "json", "table"],
};

```
Loading