Git Product home page Git Product logo

tsunit's Introduction

tsUnit

Choose a Version!

  • If you need ES5 support, please use v2.0.10 view the README for v2.0.10
  • v2.0.11 onwards is targeted at ES2015 and above and uses Promises

tsUnit is a unit testing framework for TypeScript, written in TypeScript. It allows you to encapsulate your test functions in classes and modules.

Install via NuGet:

PM> Install-Package tsUnit 

Install via NPM

> npm i tsunit.external

NOTE: Version 2.0 has breaking changes, to improve re-use between different module systems. Please read the below to see how to use version 2.0.

tsUnit comes with...

  • Built-in assertion helpers

  • Built-in HTML or TAP output, or raw data

  • A test limiter that lets you click to re-play a test, or group of tests without re-running the whole suite (thanks to Paul Atryda)

  • An easy to use test-double generator

  • Support for async testing (Version >= 2.0.2)

Simple!

It is so easy, you don't even have to download and unzip anything. It is just one file, written in TypeScript... just add tsUnit.ts to your project.

Please start a discussion if you think a feature is missing or doesn't work as expected.

Example

Test modules look like this...

    import * as tsUnit from './Scripts/tsUnit/tsUnit';
    import * as Calculations from './Scripts/Calculations';
	
    export class SimpleMathTests extends tsUnit.TestClass {
	
        private target = new Calculations.SimpleMath();
	
        addTwoNumbersWith1And2Expect3() {
             var result = this.target.addTwoNumbers(1, 2);
	
            this.areIdentical(3, result);
        }
	
        addTwoNumbersWith3And2Expect5() {
            var result = this.target.addTwoNumbers(3, 2);
	
            this.areIdentical(4, result); // Deliberate error
        }
    }

Composing your test suite goes as follows...

    import * as CalculationsTests from './Scripts/CalculationsTests';

    // "The One Liner" - you can do this in multiple stages too
    var test = new tsUnit.Test(CalculationsTests).run().showResults('results');

The multi-line version is also available... in particular this is useful if you want to re-use the result (which you can display as HTML and retrieve TAP output from).

    // Create the test suite
    var test = new tsUnit.Test(CalculationsTests);

    // Run the test
    var result = test.run();

    // Display in the element with id="results"
    result.showResults('results');

To run without a browser, you can call test.run() and use the raw result data yourself...

    // Handle the results yourself...
    var result = new tsUnit.Test(CalculationsTests).run();
    
    var outcome = (result.errors.length === 0) ? 'Test Passed' : 'Test Failed';

Or you can use the TAP (Test Anything Protocol) output:

    // TAP output...
    var tap = new tsUnit.Test(CalculationsTests).run().getTapResults();
    
    console.log(tap);

Async testing

To support async tests you must use the TestAsync class and it's test.runAsync() method.

    import * as CalculationsTests from './Scripts/CalculationsTests';

    // "The One Liner" - you can do this in multiple stages too
    var test = new tsUnit.TestAsync(CalculationsTests).runAsync().then((result) => result.showResults('results'));

Your test classes do not need to change unless you are writing an async test:

    import * as tsUnit from './Scripts/tsUnit/tsUnit';
    import * as CalculationsAsync from './Scripts/CalculationsAsync';
	
    export class AsyncMathTests extends tsUnit.TestClass {
	
        private target = new CalculationsAsync.SimpleMath();
	
        addTwoNumbersAsynchronouslyWith1And2Expect3() {
            var promise = this.target.addTwoNumbers(1, 2);
	
            // return a promise:
            return promise.then((result) => {
                this.areIdentical(3, result);
            });
            
        }
    }

Note how the method from your CalculationsAsync module returns a promise that has to be resolved before the result can be checked.

In order to allow the test runner to detect when your code is finished, your test must be a chain of promises (using .then) and you must return the last promise in that chain.

The use of the => operator allows us to access this -- if you use functions here you must provide access to the this of your test class:

    import * as tsUnit from './Scripts/tsUnit/tsUnit';
    import * as CalculationsAsync from './Scripts/CalculationsAsync';
	
    export class AsyncMathTests extends tsUnit.TestClass {
	
        private target = new CalculationsAsync.SimpleMath();
	
        addTwoNumbersAsynchronouslyWith1And2Expect3() {
            var promise = this.target.addTwoNumbers(1, 2);
	
            // save this:
            var self = this;

            return promise.then(function (result) {
                self.areIdentical(3, result);
            });
            
        }
    }

Since your code is now asynchronous, you will also not be able to use this.throws() to check that your code threw an exception. If you want to check that your result is a rejected promise, use test code like this:

    import * as tsUnit from './Scripts/tsUnit/tsUnit';
    import * as CalculationsAsync from './Scripts/CalculationsAsync';
	
    export class AsyncMathTests extends tsUnit.TestClass {
	
        private target = new CalculationsAsync.SimpleMath();
	
        divideByZeroAsynchronouslyIsRejected() {
            var promise = this.target.divide(1, 0);

            // use both parameters of then, second is onRejected callback:
            return p.then(() => {
                this.fail("expected promise to be rejected, got success");
            }, (err:Error) => {
                this.areIdentical("division by zero", err.message);
            })
        }
    }

More options for async running

Since the one-liner gets a little bit out of hand, this is how a multiline version of the async runner looks.

    // Create the test suite
    var test = new tsUnit.TestAsync(CalculationsTests);

    // Run the test
    var promise = test.runAsync();

    // await the result and show it

    promise.then(function(result) {
        // Display in the element with id="results"
        result.showResults('results');
    });

To run without a browser, you can call test.runAsync() and use the raw result data yourself...

    // Handle the results yourself...
    var promise = new tsUnit.TestAsync(CalculationsTests).runAsync();
    
    promise.then(function(result) {
        var outcome = (result.errors.length === 0) ? 'Test Passed' : 'Test Failed';
    });

Or you can use the TAP (Test Anything Protocol) output:

    // TAP output...
    // Handle the results yourself...
    var promise = new tsUnit.TestAsync(CalculationsTests).runAsync();

    promise.then(function(result) {
        var tap = result.getTapResults();
    
        console.log(tap);
    }

Remember, since the tests are run asynchronously, the results can only be delivered asynchronously.

License

Copyright 2012-2016 Steve Fenton, async support was written by and is Copyright 2016 Harald Niesche

Please read the LICENSE file for more details.

tsunit's People

Contributors

hn3000 avatar ibrahimgunduz34 avatar rostacik avatar steve-fenton avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tsunit's Issues

Problem when calling TestClass.parameterizeUnitTest multiple times

We have unit test code as follows:

import * as tsUnit from "Scripts/tsUnit/tsUnit";
import Utilities = require("Utilities");

export class MyTests extends tsUnit.TestClass
{
    parameterizedTests()
    {
        // Frist group of parameters to be tested
        this.parameterizeUnitTest(this.testMySpecialFunction,
            [
                [0, true],
                [-1.1, false],
            ]);

        // Second group of parameters to be tested
        this.parameterizeUnitTest(this.testMySpecialFunction,
            [
                [-1, true],
                [1, true],
            ]);
    }

    private testMySpecialFunction(value: number, expectedResult: boolean)
    {
        this.areIdentical(expectedResult, Utilities.mySpecialFunction(value));
    }
}

This is a simple example, and splitting up the various test parameter sets might not make much sense here, but we sometimes have more complicated tests where it makes sense to split up test cases for a particular function into different groups of parameter sets.

The problem is that when you currently run this, only the last set of parameters is being used, and the first set is never tested at all. We noticed this after seeing that some tests never failed (even if you used garbage parameters).

The reason for this is as follows:
in tsUnit.ts line 517 and following, there is:

export class TestClass extends TestContext {
    protected parameterizeUnitTest(method: Function, parametersArray: any[][]) {
        (<any>method).parameters = parametersArray;
    }
}

So, what happens is that when you call parameterizeUnitTest a second time (after having parameterized a test earlier), the previous sets of parameters get overwritten by the last one.

--> Could this be changed, so that a new array of parameters gets added/appended to the existing one, instead of overwriting the existing parameters array?

Having trouble running in NodeJs project.

http://stackoverflow.com/q/26788607/1757491

So I found tsUnit library that I am trying to figure out how to use in a nodeJS project. I did find that the example projects on the tsUnit page have .html files but I'm hoping that I could just run the unit test.

import tsUnit = require('../tsUnit');
module CalcTest {
class TryATest extends tsUnit.TestClass {
test() {
this.areIdentical(4,4);
}
}
}
var test = new tsUnit.Test(CalcTest);

var result = test.run();
The result I get is:

var previousHandler = window.onhashchange;
ReferenceError: window is not defined
at TestRunLimiter.setRefreshOnLinksWithHash
at new TestRunLimiter
at new Test
at Object.
at Module._compile
at Object.Module._extensions..js
at Module.load
at Function.Module._load
at Function.Module.runMain
at startup (node.js:119:16)

Package for non-windows users

It'd be nice to fit this with a package.json and get it into the NPM registry so that folks not using the .NET stack can easily get and use it.

Ignore internal/private functions from Test classes

How to exclude (internal) functions from a test class?
Currently _doPrepare() will also execute as a Test.

module Tests {
    export class DummyTest extends tsUnit.TestClass{
        private _doPrepare(i:number) {
            //Prepare the class with 'i'
        }
        public checkOne() {
            this._doPrepare(5);
            this._doPrepare(7);
            this.isTrue(this.internal);
        }
        public checkTwo() {
            this._doPrepare(5);
            this._doPrepare(8);
            this.isFalse(this.internal);
        }
    }
}

Maybe ignore all functions that start with a '_' (or a predefined RegEx Pattern), or add a function for adding functions that should be ignored.

No TestAsync class in the NuGet package?

I'm referencing 2.0.3 via NuGet, and I'm not seeing a TestAsync class. Everything I've read here leads me to expect it there. Is there another package for async testing or something?

tsUnit.Examples failes

I load project "tsUnit.Examples" into VS 2015, open file "default.htm", and start without debugging. I get a Webpage Error as follows:

Line: 13
Error: Unable to get property 'Test' of undefined or null reference

Suspect software needs some work.

Thanks

Compiling problems

Hi,

I have installed tsUnit using

npm install tsunit.external

but I get an error when running the simplest file: Already at the import, it fails with the error:

node_modules/tsunit.external/tsUnit.ts(579,40): error TS2304: Cannot find name 'Set'.
node_modules/tsunit.external/tsUnit.ts(595,29): error TS2304: Cannot find name 'Set'.
node_modules/tsunit.external/tsUnit.ts(597,22): error TS2339: Property 'from' does not exist on type 'ArrayConstructor'.

I guess that there are some definitions missing? but what? Have I omitted something?

Cheers,

Kristofer

tsUnit.ts external compiling error

The external tsUnit.ts has a type mismatch error on line 260, that is raised on compile and has the following message:

tsUnit.ts(260,37): error TS2345: Argument of type 'Event' is not assignable to parameter of type 'HashChangeEvent'.

I believe this is an internal error of the library caused by a bad type signature.

failing async tests throw error - testing stops and no results are shown

When running async tests and one test fails, testing stops, and results are not shown.
A simplified version of my setup:

export default class AsyncTest extends tsUnit.TestClass
{
    testAsync()
    {
    	return new Promise((resolve,reject) => {
    		this.isTrue(false);
    	});
    }
}

tsUnit.ts:499 Uncaught (in promise) Error: isTrue failed when given {boolean} "false"
    at AsyncTest.getError (tsUnit.ts:499)
    at AsyncTest.isTrue (tsUnit.ts:404)
    at AsyncTest.testAsync (AsyncTest.ts:15)
    at Promise.resolve.then (tsUnitAsync.ts:119)

this.setState is never called:

var testAsync = new TestAsync({AsyncTest});
testAsync.runAsync().then(resultAsync => {
    this.setState({resultAsync:resultAsync});

Forks can not be installed via npm with git url

Because the package.json is deep inside the project structure, the module can not be installed straight from git.

Since tsunit now uses the umd module format, it should be possible to move the package.json to the top and get rid of the copying at least for npm. (And that would also reduce the problem with contributors who forget to properly adapt the build scripts ...)

What do you think?

Can't run tests

I installed the tsUnit and wrote my UnitTests, but unfortunately Visual Studio doesn't find my tests and therefore can't run them.
Is there anything I have to todo apart from installing the package?
Thanks a lot!

HashChangeEvent not found

I can't compile tsUnit w/o getting multiple errors:
Error 1 Cannot find name 'HashChangeEvent'. C:\Users\laubd\Downloads\tsUnit-master\tsUnit-master\tsUnit.Node.Examples\node_modules\tsunit.external\tsUnit.ts 256 49 tsUnit.Node.Examples

Question: why not standart method names?

It will be much easier to use tsUnit if there are standard methods:

setUp(), tearDown(), assertTrue(), assertEquals() /* instead of areIdentical() */, etc.

Steve, it's up to you, sure. But I use TDD for years and it will be much easier to people like me to use standard named methods. Unit test for CPP, Java, Php, Javascript(with qunit) are very similar. Even if you had not used qunit before, but have experience with JUnit - you can just guess and it will work fine in most cases. But for tsUnit you need to memorize new method names.

Also, you won't need to pay so much attention to documentation - people already expect some behaviour, if tsUnit will match this behaviour - they will heve no need in documentation. That can make tsUnit more popular. Otherwize, someone might create alternative framework.

What do you think?

npm package

Hey Steve - have you considered publishing this as an npm package?

Async Support?

I would really like to roll out tsUnit within my company for unit testing TypeScript as I don't really like Jasmine; but the one main blocker we have at the moment is that tsUnit doesn't support async calls.
With async calls and karma support; tsUnit could be really big.

No tests found with es6 target

I'm testing using Chrome 49.

If you set your target to ES6 all of your tests disappear.

for (var unitTestName in testClass) {
in ES6 none of the functions are returned in the for. I'm not much of a javascript guy and I tried a quick google to see if this is something folks are talking about and came up dry, but I did some tests myself and found that to be the case.

To be clear I'm not talking about transpiling, just using raw ES6.

I noticed this when I switched my project to use ES6 for unrelated reasons and my tests all stopped showing up.

Error in README related to getTapResults usage example

Readme currently shows this code:
var tap = new tsUnit.Test(CalculationsTests).getTapResults();

It should be:
var tap = new tsUnit.Test(CalculationsTests).run().getTapResults();

Pretty minor, but confused me for a few minutes...

Thanks.

a failure or exception in setUp causes async tests to hang

I think just because the call to testClass.setUp() needs to be inside the Promise in the code below:

    protected runSingleTestAsync(
        testClass: TestClass, 
        unitTestName: string, 
        testsGroupName: string, 
        parameters: any[][] = null, 
        parameterSetIndex: number = null
    ):Promise<this> {
        testClass.setUp && testClass.setUp();

        // running everything inside .then saves us a try/catch
        return Promise.resolve().then(()=>{
            var dynamicTestClass: any = testClass;
            var args = (parameterSetIndex !== null) ? parameters[parameterSetIndex] : null;
            return dynamicTestClass[unitTestName].apply(testClass, args);
        }).then(() => {
            this.passes.push(new TestDescription(testsGroupName, unitTestName, parameterSetIndex, 'OK'));
            return this;
        }, (err:any) => {
            this.errors.push(new TestDescription(testsGroupName, unitTestName, parameterSetIndex, err.toString()));
            return this;
        });
    }

Can't run tests (installed with npm and run with ts-node)

After installing the library using npm (npm install tsunit.external) and writing a dummy test class like this (QueryHelperTest.ts)

import * as tsUnit from './../node_modules/tsunit.external/tsUnit';
import * as queryHelper from './../src/app/storedash/helpers/QueryHelper.ts';

export class QueryHelperTest extends tsUnit.TestClass {

    badlyFormedQueryThrowsError() {
        this.areIdentical(1,1);
    }

};

and a runner script like this (tests.ts)

import * as tsUnit from './../../node_modules/tsunit.external/tsUnit';
import {QueryHelperTest} from './../QueryHelperTest';

let tap = new tsUnit.Test(QueryHelperTest).run().getTapResults();

console.log(tap);

and then running the script individually using ts-node, I get an error message:

felipe@felipe-VirtualBox:~/storedash-ui$ ts-node test/runner/tests.ts
SyntaxError: Unexpected token export
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:387:25)
    at Module._extensions..js (module.js:422:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/usr/local/lib/node_modules/ts-node/src/index.ts:304:16)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (/home/felipe/storedash-ui/test/runner/tests.ts:1:19)
    at Module._compile (module.js:413:34)

Is there anything obviously wrong here? Thanks

Build errors in Visual Studio

Working with Visual Studio 2017 community edition
TypeScript version 2.8.4
tsUnit NuGet package version 2.0.11
ASP.NET version 4.6.1

When I try to build my application I get the following errors:

Error TS2304: Build:Cannot find name 'Set'. (579, 40)
Error TS2304: Build:Cannot find name 'Set'. (579, 40)
Error TS2304: Build:Cannot find name 'Set'. (595, 29)
Error TS2304: Build:Cannot find name 'Set'. (595, 29)
Error TS2339: Build:Property 'from' does not exist on type 'ArrayConstructor'. (597, 22)
Error TS2339: Build:Property 'from' does not exist on type 'ArrayConstructor'. (597, 22)
Error TS2693: Build:'Promise' only refers to a type, but is being used as a value here. (103, 16)
Error TS2693: Build:'Promise' only refers to a type, but is being used as a value here. (103, 16)
Error TS2693: Build:'Promise' only refers to a type, but is being used as a value here. (114, 16)
Error TS2693: Build:'Promise' only refers to a type, but is being used as a value here. (114, 16)

bug in TestClass.throws

It looks like the "throws" statement in TestClass is not working.
The following code works fine (test succeeds because exception is thrown):

    goodTest5()
    {
        this.throws(() =>
        {
            console.log("Exception thrown. Test should succeed.");
            throw new Error("exception!")
        }, "Code should throw an exception.");
    }

However, the following code does not work as expected (test still succeeds, even though no exception is thrown):

    badTest5()
    {
        this.throws(() =>
        {
            console.log("No exception thrown here. Test should fail!");
        }, "Code should throw an exception.");
    }

Expected behavior: badTest5 should be a failed test.
Observed behavior: badTest5 ends up in the passed tests.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.