Showing posts with label unit testing. Show all posts
Showing posts with label unit testing. Show all posts

Wednesday, November 22, 2017

Writing unit tests with Vuejs and Poi

Poi is great. It's fantastic! It's one of the tools that were very much missing from the landscape. Now that we already have it let's explore what we can do with it. Let's get serious!

This time we're going to create a POI-based project that will support both Vue and unit testing.

First we need to have a project. A simple npm init will do. When asked to give the test command write poi test and you're done.

$ npm init
...
test command: poi test
...

Is this ok? (yes)

That was easy. Now let's install the required dependencies (there are quite a few of them but we'll go through the list and I will explain what each one does):

$ npm install --save-dev poi poi-preset-karma \
    webpack karma mocha chai karma-webpack karma-mocha karma-chai \
    vue vue-test-utils

poi is our build system so it is obvious it needs to be installed. poi-preset-karma is a preset for poi for it to know what to do when you execute poi test. It will use karma to run the tests.

webpack and karma-webpack allow to use webpack to bundle all the files

mocha is the testing framework giving you BDD-like tests with describe and it. karma-mocha is a package that allows easy integration of Karma and Mocha.

chai is a fantastic library for writing expectations. Similarly to Mocha, karma-chai makes it easy to integrate Karma with Chai.

And last but not least we top it with some Vue sauce. vue is our beloved frontend framework and vue-test-utils is a library that aids testing.

Let's write some tests

The default folder structure assumes unit tests to be located in test/unit folder and the files to be named like something.test.js. So let's create one:

test/unit/example.test.js

it('will pass', () => {
  expect(1).to.equal(1)
})

Easy, right? For Poi to know what to do when we run poi test we need to use a preset. To do that we'll create a poi.config.js file like so:

module.exports = {
  presets: [
    require('poi-preset-karma')({
      frameworks: [ 'mocha', 'chai' ]
    })
  ]
}

As you can see there we use Chai asserts. For Mocha to know about Chai we need to tell the Karma preset that both Mocha and Chai are to be used.

Now all that remains is to run the tests. There are 2 options for running:

  • Run just once and finish
  • Run continuously in the background and re-run tests when files change

To just run the tests and finish you issue the command

$ npm test

This works because test is a top-level npm command.

To run tests continuously with automatic re-running do this:

$ npm test -- --watch

Let's decipher the bits. npm test is pretty much obvious at this point. The double-dash is a way to tell npm hey, when you run the command specified in the scripts section then add all the parameters that follow to the execution. In our case the --watch parameter enables watching changes on files and automatic re-running of all the tests.

Poi and continuous integration server

Running tests in a real browser is great because they will be testing components in their natural habitat. It poses however a difficult problem when running them on a headless continuous integration server. This is a common problem and to address that Poi has a switch that uses ChromeHeadless instead of the regular Chrome:

$ npm test -- --headless

Of course you can combine them and run headless tests in watch mode on a remote machine via SSH using Vim or Emacs as your text editor - especially if your primary work computer is running Windows and you want things to go fast(er). The possibilities are endless.

Debugging

By default tests are being executed on Google Chrome. The page you'll see contains a little DEBUG button. When you click it a new tab will open where you can set breakpoints and examine your code. One thing to note is that by default there is a limit to how long one unit test can take (2s) and you will most likely exceed that limit if you pause in a test method. Don't be alarmed by that - just re-run your tests without breakpoints and you'll see if it works or not.

Please note that the tests in debug mode won't re-run by themselves when you change things in the sources. You need to refresh the page to start a new test run. This is done so that hot-module reloading doesn't kick in in the middle of your debug session. Very convenient!

Let's go Vueing

The time has come to make a real test that uses Vuejs. So let's create one in test/unit/components/Clicker.js that will check if upon clicking on the component a custom event will be emitted:

import Vue from 'vue'
import { mount } from 'vue-test-utils'

import Clicker from '@/components/Clicker.vue'

describe('Component: Clicker', () => {
  it('will emit "clicked" event when interacted with', () => {
    // given
    const wrapper = mount(Clicker)

    // when
    wrapper.vm.$el.click()

    // then
    expect(wrapper.emitted().clicked).to.deep.equal([ [ 'Here!' ] ])
  })
})

Now in the root folder let's create src/components and inside that let's create our component as a single-file component Clicker.vue:

<template>
  <h1 @click="$emit('clicked', 'Here!')">Hello!</h1>
</tempalte>

That's it! It is really that simple!

Post scriptum

This barely scratches the surface of what is possible with Poi but at the same time it does cover a lot of configuration that you don't need to write yourself. Just looking at the starter template for webpack-simple shows how much is being done behind the scenes.

Happy testing!

Wednesday, March 21, 2012

Spock - the testing as it should be done

It's not very often when I get really excited about some piece of software. I'm not saying it doesn't happen because that wouldn't really be true but those times when I get the willies just after taking a brief look at something are really rare. Today is that day. Today I met Spock.

Well technically speaking, I met this guy, Luke Daley, on 33rd Degree conference when he gave a talk about Spock and how it differs from what you can do with regular JUnit tests.

OK. Enough of about the conference - let's see some code!


If you put this into an example.groovy file and execute it it'll actually run 2 unit tests. On the test we see the following sections:

  • We see that Spock is being grabbed (excluding Groovy since Spock tries to pull in some non-existent version)
  • We then create an Example Specification (that's how you should read the class declaration line)
  • We then say that we define that a sum of a and b is equal c (whatever those are)
  • Then some magic happens: we say that we expect that a + b is equal to c
  • And last but not least we define the set of data to create separate tests in a tabular, fitness-like form

Here's the output of that script (you should run it yourself to see it really do all the work!):
JUnit 4 Runner, Tests: 2, Failures: 0, Time: 15
Isn't it great? You spent about no time creating a few lines of code, got 2 test cases in return that execute in no time and are no match for JUnit's @Parametrized tests (which sucks big time by the way).

This is obviously the absolutely simplest example possible. There's a lot more to Spock than meets the eye here and the deeper you go there the more you wonder how's all that even possible. This is why I'll stick to Groovy as the most versatile, universal, non-problematic and powerful language ever created for the JVM.

Monday, January 10, 2011

camelCase for human beings

Reading lots of characters glued together is a very good thing for the compiler. Human beings tend to prefer spaces rather than a set of lowercase characters separated with uppercase characters to distinguish words. It's just how we were taught since we were very young...

In case of unit test in Groovy we can actually name our tests with spaces! Here's an example:
import org.junit.Test

class ExampleTests {
@Test void 'This test verifies nothing but is a good example'() {
assert 1 == 1
}
}
When later on you're reading the name of the test that failed it's a whole lot easier than to read the same in camelCase.

Converting camelCase to human text

I thought I'll give a string an additional method so that whenever I have a camelCase string I can convert it easily to something that's easier to read:
String.metaClass.humanify = {
def r = ""

delegate.eachWithIndex { c, i ->
if (i == 0) r += c.toUpperCase()
else if (c in 'A'..'Z') r += ' ' + c.toLowerCase()
else r += c
}

return r
}

From now on it's easy to read camelCase when it's humanized :D

Friday, January 7, 2011

Groovy/Grails DSL testing

Today I faced a usual task of testing a controller action that utilizes the withCriteria call to fetch some data from the database. Usually what I do in situation like this is I write an integration test, have the database mocked using in-memory instance of HSQLDb and all is nice and dandy.

This time I didn't have the luxury to have the database in place. I will not bore you why that is the case - it simply is. What I didn't want to do was to just let the thing be untested so I've decided to create a ultra-minimalistic framework for testing such DSLs in Groovy.

First of all, it all bases on the assumption that you don't care about the actual results the DSL brings. What you do care about is the fact that certain parts of the DSL have been called in a particular order and with proper arguments. To put this in context: you don't care that the withCriteria DSL will be in reality transformed into SQL but you do care that what you wrote will be as you expect it to be.

So the following class has emerged:
package groovy.test

class DSLTester {
static mock(clazz, method, result) {
def tester = new DSLTester()
clazz.metaClass.static."${method}" = { Closure dsl ->
dsl.delegate = tester
dsl.resolveStrategy = Closure.DELEGATE_FIRST
dsl()
return result
}
return tester
}

def result = []

def methodMissing(String name, args) {
result << [ name: name, args: args.toList() ]
}
}

What it does is it executes the closure passed on as the DSL to whatever static method we decide to test and catches all the missing calls as if they were proper DSL calls. You might find the args.toList() part to be a little bit strange. This is to allow use simple comparison in tests - read on to find how.

To give you an example first let's define the Person class:
class Person {
String firstName
String lastName
}

With that in hand let's create a home controller that will just print all the people ordered by firstName:
class HomeController {
def index = {
def people = Person.withCriteria {
order "lastName"
}

[ people: people ]
}
}

To test the withCriteria closure let's utilize the DSLTester class:
import groovy.test.DSLTester
import grails.test.ControllerUnitTestCase
import org.junit.Test

class HomeControllerTests extends ControllerUnitTestCase {
void testExecuteDSL() {
def mock = DSLTester.mock(Person, 'withCriteria', [])
def actual = controller.index()
assert mock.result == [ [ name: 'order', args: [ 'lastName' ] ] ]
}
}

As you can see the only assertion that I make here is that the order will be properly set to 'lastName' which is what we wanted in the first place.

There's tons of ways you could improve this. You could for example come up with a nice way to verify expected methods have been called with the proper arguments instead of declaring a huge list with hashes containing everything. Sky is the limit :)

The main motivation behind this sort of test is to provide means to test only your code and to test it in complete isolation. It might be perfectly understandable that since the code that uses withCriteria has such a strong dependency on the database that testing it in isolation makes no sense. I however like to keep things isolated :)

Friday, November 26, 2010

STS and Grails - running JUnit tests from IDE

Hi folks!

Have you been wondering how to run JUnit 4 tests under STS so that the the tests are recognized and executed properly?

junit.framework.AssertionFailedError: No tests found in

I guess most of you writing tests for your Grails application have seen this one under Idea or STS. The IDE just doesn't see the right tests by itself... But there's hope!

Here's a definition of a class that when used in conjunction with the @RunWith annotation allows the IDE to run those test properly:
package com.aplaline.example.test;

import org.codehaus.groovy.grails.test.GrailsTestTargetPattern;
import org.codehaus.groovy.grails.test.junit4.runner.GrailsTestCaseRunner;

@SuppressWarnings("rawtypes")
public class GrailsJUnit4Runner extends GrailsTestCaseRunner {
public GrailsJUnit4Runner(Class testClass) {
super(testClass, new GrailsTestTargetPattern[0]);
}
}

And here's an example test that uses it:
package com.aplaline.example

import grails.test.*

import org.junit.Test;
import org.junit.runner.RunWith;
import com.aplaline.example.test.GrailsJUnit4Runner;

@RunWith(GrailsJUnit4Runner)
class CalculatorServiceTests extends GrailsUnitTestCase {
@Test
void canAddTwoNumbers() {
// given
def service = new CalculatorService()

// when
def actual = service.sum(1, 2)

// then
assert actual == 3
}
}

See - that wasn't hard, was it?

I hope it'll help you out test your code more efficiently :)

Have fun!!!

Sunday, April 4, 2010

JTK - the killer emerges

Hi all,

recently I've been shocked by how many people write their unit tests without actually putting any assertions in them. Can you imagine that?

Long story short a good friend of mine proposed that we write an application/maven plugin called JTK (which stands for Java Test Killer) that will check the test cases and will provide a clear overview of how many of the tests that the project has make no sense based on the fact that they don't call any assertions.

You can check out the sources on bitbucket.org (it's obviously managed under Mercurial so you'll have to have the client installed which you can get from here)

There's also a couple of tools guarding the process of creation: Hudson and Sonar.
The maven repository (in case you'd like to give it a spin) is here (snapshots only as of this moment but we're planning on releasing it eventually).

We're at a very early stage but if you're interested in helping out let me know!


Monday, December 7, 2009

Code coverage and Enum types

Hi,

I've been trying really hard to achieve 100% code coverage on one of the projects I'm working on right now. Pretty much all my business code showed the desired code coverage right up to the point where I introduced enumeration.

First let me explain why I wanted to get to the 100% in the first place.

Whenever I'm writing code that should be covered by unit tests (which is pretty much always nowadays) I'd like to be reminded (by either the code coverage results in CI or by the IDE) that some of the edge cases have not been tested yet. I know this might sound bad in the first place because I should only write as much code as required to satisfy the test I wrote but still - there are cases where the business code I produced does a little bit more than what's in the test. So it's a good idea to keep the 100% test coverage at all times so that once it drops below this magic number I'll notice immediately that something has been skipped.

Back to enumerations.

Those guys contain synthetic methods generated by the compiler (like valueOf and values) that do exist in the byte code but have no corresponding lines in the code itself. This means that there's more that meets the eye from the code's perspective but the code coverage tools I use (Cobertura and EclEmma) know only about byte code and they couldn't care less if the method they are testing came from the code itself or if it was dynamically generated by the compiler.

To that end, whenever I use an Enum the overall coverage drops like stone which simply looks awful.



But there's hope! One line of stupid test and all is green again.

MyEnum.valueOf(MyEnum.VALUE.toString());








I admit that the actual value of this test is minimum but the real reason to do that is to allow yourself the luxury to always react on the drop of coverage below 100% instead of manually checking every time if what's missing is really something we don't care about.

I hope this helps.

Wednesday, April 15, 2009

NUnit template for ASP.NET MVC

Hi there,

I've been struggling a bit with the automatic addition of NUnit unit tests to ASP.NET MVC project in Visual Web Developer. I wanted to have it the same way it works with the VisualStudio unit test framework that is being shown over and over again on the net.

So here's the complete solution: just unzip it, run install.bat and enjoy!

ASP.NET-MVC-NUnitTemplate.zip

Additionally to the standard files you'd expect to be in place there's a NUnit project file called UnitTests.nunit. It's already configured and ready to go. To open it with the NUnit test runner do a right click on it, select "Open with...", add a new program by using the "Add" button, select the nunit.exe file, click ok, highlight NUnit in the list, click "Set as Default" and click OK. From now on everytime you double-click on it you'll run the NUnit GUI test runner which is pretty much what you'd expect.

Padcom.

Sunday, December 28, 2008

Running unit tests during builds in Visual Studio .NET - part 2

Hi all,

as I've mentioned in my previous post it's quite easy to implement running tests during build process of VisualStudio. Now not everyone is comfortable with using a set of 3rd party tasks to do simple things. This time we're going to simplify things a little bit and use the Exec task of MSBuild that already comes with the standard installation.

We're going to start as previously with the XML style sheet that will convert the XML output to a format that's understandable by VisualStudio. Save the following content into your project under VSTestFormat.xslt:


<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method='text'/>

<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="test-results">
<xsl:apply-templates select="//test-case[failure]"/>
</xsl:template>

<xsl:template match="test-case">
<xsl:value-of select="substring-before(substring-after(failure/stack-trace, ' in '), ':line')"/>
<xsl:text>(</xsl:text>
<xsl:value-of select="normalize-space(substring-after(substring-after(failure/stack-trace, ' in '), ':line '))"/>
<xsl:text>)</xsl:text>
<xsl:text> : warning NU001: </xsl:text>
<xsl:value-of select="@name"/><xsl:text>: </xsl:text>
<xsl:value-of select="normalize-space(child::node()/message)" />
<xsl:text disable-output-escaping='yes'>&#xD;&#xA;</xsl:text>
</xsl:template>
</xsl:stylesheet>


Next we're going to add the task after building the project (that goes into the [projectname].csproj file):


<Target Name="AfterBuild">
<Exec Command='"$(ProgramFiles)\Nunit 2.4.8\bin\nunit-console.exe" $(OutputPath)$(AssemblyName).dll /xml=$(OutputPath)nunit-results.xml /transform=VSTestFormat.xslt /noshadow /nologo /nodots' />
</Target>


That's it! Now when you'll build your project it is going to run tests before returning to the editor and all failing tests are converted to a list of entries in the "Error List" window of VisualStudio.

Let me make one note here: This solution works perfectly with all IDEs - the full-blown one as well as with Express editions.

For those that don't like to experiment and just want to start building tests here's a VisualStudio template ready to use. Please note that it's provided "AS-IS" without any warranty so use it at your own risk.

NUnitTests.zip

Happy building!

Tuesday, December 23, 2008

Running unit tests during builds in Visual Studio .NET

Hi there,

Some time ago I've attended a refactoring training provided by my employer. One of the interesting things there was that the project we worked on had unit tests hooked up to the build process. Now that I'm learning the .NET platform and the tools that come with it I've decided to give it a try and to integrate NUnit into the build process of a class library.

Visual Studio creates its projects in MSBuild format. That means that we can customize/extend the build process in a standard fashion as MSBuild is the standard tool (aside from NAnt) used to build .NET projects.

Here are the steps I took to enable such integration:

  1. Install NUnit (this procedure assumes the version 2.4.8 - note the version in ToolPath parameter of NUnit task).
  2. Install MSBuild community tasks (http://msbuildtasks.tigris.org/)
  3. Add the following lines to your class library project (.csproj) with tests (output file must be named "something.Tests.dll")

    <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
    <ItemGroup>
    <TestAssemblies Include="$(OutputPath)\$(AssemblyName).dll" />
    </ItemGroup>
    <Target Name="AfterBuild">
    <NUnit Assemblies="@(TestAssemblies)" ToolPath="$(ProgramFiles)\Nunit 2.4.8\bin\" XsltTransformFile="vsfmt.xslt" OutputXmlFile="$(OutputPath)\nunit-results.xml"/>
    </Target>

  4. Copy the following content into vsfmt.xslt in your test project path or somewhere else (remember to modify XsltTransformFile parameter if you store it somewhere else):

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method='text'/>

    <xsl:template match="/">
    <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="test-results">
    <xsl:apply-templates select="//test-case[failure]"/>
    </xsl:template>

    <xsl:template match="test-case">
    <xsl:value-of select="substring-before(substring-after(failure/stack-trace, ' in '), ':line')"/>
    <xsl:text>(</xsl:text>
    <xsl:value-of select="normalize-space(substring-after(substring-after(failure/stack-trace, ' in '), ':line '))"/>
    <xsl:text>)</xsl:text>
    <xsl:text> : warning NU001: </xsl:text>
    <xsl:value-of select="@name"/><xsl:text>: </xsl:text>
    <xsl:value-of select="normalize-space(child::node()/message)" />
    <xsl:text disable-output-escaping='yes'>&#xD;&#xA;</xsl:text>
    </xsl:template>
    </xsl:stylesheet>

  5. Switch to VS - a dialog should appear that the project file has changed. Click "Reload".
  6. Rebuild solution - if there are any test cases they'll get executed as part of the build process.
  7. (optional) Add the following parameter to NUnit task if you don't want your unit tests to fail the build but rather to issue warnings:
    ContinueOnError="true"

    For example:

    <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
    <ItemGroup>
    <TestAssemblies Include="$(OutputPath)\$(AssemblyName).dll" />
    </ItemGroup>
    <Target Name="AfterBuild">
    <NUnit ContinueOnError="true" Assemblies="@(TestAssemblies)" ToolPath="$(ProgramFiles)\Nunit 2.4.8\bin\" XsltTransformFile="vsfmt.xslt" OutputXmlFile="$(OutputPath)\nunit-results.xml"/>
    </Target>

Remember that using this kind of integration with unit testing framework forces developers to create unit tests that are really fast. Nobody likes to wait for the build process to complete.

While working on this integration I've used the following pages as references:

http://blogs.msdn.com/msbuild/archive/2006/11/03/msbuild-visual-studio-aware-error-messages-and-message-formats.aspx
http://www.w3.org/TR/xpath#section-String-Functions
http://blog.maartenballiauw.be/category/NUnit.aspx
http://www.nunit.org
http://msbuildtasks.tigris.org


Happy building!