Skip to content

Instantly share code, notes, and snippets.

@adamchester
Created July 18, 2012 04:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamchester/3134237 to your computer and use it in GitHub Desktop.
Save adamchester/3134237 to your computer and use it in GitHub Desktop.
A simple test assertion DSL

Why?

I am not good at writing bug-free code in JavaScript or CoffeeScript. I am equally not good at writing bug-free tests. It would be nice to have a way to quickly build a basic 'safety net' for my code, and be able to describe the tests in a format less verbose than 'describe->it-should->etc'.

It should also be a good learning experience.

Goals

  1. Short and sweet syntax for asserting basic behaviour.
  2. It should be relatively easy to create new ad-hoc assertions.

How should it work?

# describe how they should work
describe 'asserters.verify', ->
	# describe a mock module that 'exports' various things
	myModule =
		export1: {a:'a', b:'b'}
		export2: i:'am', one:'object'
		funcWithNoArgs: (callback) -> callback(null, "with", "some", "extra")
		funcWithOneArg: (input, callback) ->
			assert _.isFunction(callback), "callback must be a function"
			callback(new Error("error") if input is "error")
		funcWithTwoArgs: (input1, input2, callback) ->
			assert _.isFunction(callback), "callback must be a function"
			if input1 is "error" or input2 is "error"
				callback(new Error("error"))
			else
				callback(null, "with", "some", "extra")

	# describe the assertions that need to be performed
	myAsserts =
		abc: [ new Asserter(), new Asserter() ] # abc doesn't exist, but the asserter doesnt require it
		# abc2: [ a.IsDefined ] # this would fail
		# def: [ new AssertIsDefined() ] # def doesn't exist
		export1: [ a.IsObject, a.HasFields(['a', 'b']) ]
		export2: [ a.IsObject, a.HasFields(['i', 'one']) ]
		funcWithNoArgs: [ a.CanCallback() ]
		funcWithTwoArgs: [ a.CanCallbackError('success', 'error'), a.CanCallback('success', 'success') ]
		funcWithOneArg: [ a.CanCallbackError('error'), a.CanCallback('success') ]

	it 'should get no errors when verified', (done) -> a.verify myAsserts, myModule, done
@liammclennan
Copy link

Won't this make it hard to change/brittle? Looks like you are missing a type system.

@adamchester
Copy link
Author

You are right about me missing a type system, but I don't think it will make things more brittle than my current strategy. Perhaps your code is more bug-free than mine?

@liammclennan
Copy link

Yeah, that's not it.

@adamchester
Copy link
Author

Can you point me in the direction of a topic that explains this? As you know, I'm new (ish) to dynamic typing languages and if testing my code at a slightly lower / more "basic" level than normal (while im learning) is going to make it more brittle, clearly I have some reading to do :)

@liammclennan
Copy link

My personal grain-of-salt opinion is that you should test the behaviour, not the specifics of an implementation. If you do want fake types have a look at https://developers.google.com/closure/compiler/. There is also a typed version of CoffeeScript but I can't find a link.

@adamchester
Copy link
Author

It's a bit hard to get to the behaviour part when I can't even get the exports/input/output right!

Do you think this assert would test behaviour? a.CanCallbackError('error')

@liammclennan
Copy link

I believe that is testing implementation details. Over-specification. However, I think you should do it. It will either work for you or become painful and suggest something else.

@adamchester
Copy link
Author

Let me get this straight, "given the input string 'error' it should result in an error", that is testing implementation?

Where does it assume how that input resulted in an error? It could be implemented as an if input is error statement, or it could ask a network service to validate the string, it could lookup a file in a folder to see if the string exists... none of those possible implementations is being assumed or tested. Right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment