Showing posts with label groovy. Show all posts
Showing posts with label groovy. Show all posts

22 February 2017

Using Spockframework to unroll donzs of test cases from a few of them

Part of working on spwrap, I am working to writing unit and integration tests form this tiny framework.

I've used spockframework to write some test cases on a project in my current company, I find it very handy and complete framework.

Because spockframework is written in Groovy, it provides very dynamic features that is hard to achieve in other Java-based testing frameworks, at least the syntax of other testing/mocking frameworks will not as good as Spock.

Besides Spock is provides basic testing functionality, it provides what they called "interaction-based testing" (a.k.a. Mocking) and one amazing feature what is "Data Driven testing"

In this post I'll talk about how I used both of them to write 8 test cases and got more than 150 unit test generated.

One of the basic spwrap features is to let user call stored procedures that return result sets and output parameters, and it is user responsibility to extract the data from these JDBC interfaces.

This mapping is done in Mappers, where the user have to implement one of two interfaces either ResultSetMapper or TypedOutputParameterMapper.

example of class implements both interfaces:


public class Customer implements TypedOutputParamMapper<Customer>, ResultSetMapper<Customer> {

    private Integer id;
    private String firstName, lastName;

    @Override
    public Customer map(Result<?> result) {
        if (result.isResultSet()) {// for ResultSetMapper
            return new Customer(result.getInt(1), result.getString(2), result.getString(3));
        } else { // for TypedOutputParamMapper
            return new Customer(null, result.getString(1), result.getString(2));
        }
    }

The map function above have one parameter of Type Result, which is a wrapper for both java.sql.ResultSet and java.sql.CallableStatement

The Result class has two subclasses (ResultSetWrapper and CallableStatementWrapper) that delegate the call to ResultSet and CallableStatement respectively and re-throw SQLException as non-checked CallException.

Each class of the Wrapper classes (ResultSetWrapper and CallableStatementWrapper) has about 40 methods like getString, getBoolean, getByte, getShort, getInt, getLong, getFloat, etc.

So, I need to write about 40 * 2 (1 success path and 1 fail path) * 2 (2 classes to test) ~= 160 method.

so let's see how we accomplish this using spock:


def callableStatementWrapper
def callableStatementMock = Mock(CallableStatement)

@Shared METHOD_NAMES = ["getString", "getBoolean", "getByte", "getShort", "getInt",
                        "getLong", "getFloat", "getDouble", "getBytes", "getDate", "getTime",
                        "getTimestamp", "getObject", "getBigDecimal", "getRef", "getBlob", "getClob",
                        "getArray", "getURL"];
void setup() {
    callableStatementWrapper = new CallableStatementWrapper(callableStatementMock, 1)
}

def "calling #methodName(int) on CallableStatementWrapper calls the same method name on CallableStatement" (String methodName){
    when:
        callableStatementWrapper."$methodName"(1)
    then:
        1 * callableStatementMock./get.*/(_)
    where:
        methodName << METHOD_NAMES
}

The first line is just a definition for a reference that will hold the object that we need to test which is a CallableStatementWrapper.

The second line is mocking the java.sql.CallableStatement into an variable named callableStatementMock

then we have a static (shared) field of type array of string, actually these are method names on CallableStatementWrapper we need to test.

The setup method instantiate the CallableStatementWrapper using the callableStatementMock mocked object.

the test method do 2 important things:

1. In the when block we say: whenever the user calls callableStatementWrapper. (some dynamic method name that we will supply later in the where block)

2. in the then block: we say, expect 1 call to the mocked object getXXX method that takes any parameter (see interaction-based testing for more details)

3. in the where block, we substitute the methodName in step 1 (when step) by the method name from the static array of method names METHOD_NAMES Array.

When run this test,  and because of the class annotate by @Unroll, we got about 20 test case runs for us.

see the test cases on github for CallableStatementWrapper and ResultSetWrapper.

Hope you can find spock and spwrap helpful!




30 September 2016

Gradle is awsome

Gradle the build tool for Java and Android (and other languages) is really powerful.

I am brand new to gradle, this is the first time I try it, and I find it really powerful.

I am working - for fun - on some spring boot + angular project , I decided to go with gradle because I like Groovy (The language that grails is written as a DSL; however gradle is written in Java as well as groovy).

However Eclipse support is not as much good as Maven, but I started the spring boot using gradle as the build tool and every thing is fine.

Now I need to build the spring project as well as the angular project (which is based on angular-seed that uses npm and bower).

I find a plugin for gradle for this task (gradle-node-plugin), this plugin allow you to do:

gradle npm-install

so, the npm install command will run and that what I need, but I need it to run with gradle build command.

First the npm-install task of gradle run by default  package.js file found in src/main/java, So I have to write my own task to make it uses spring-boot conventions (src/main/resources/static)

And thanks to the author of this plugin, he makes it easily to extend his plugin, so I wrote:

task my_npm_install(type: NpmTask) {
description = "Installs dependencies from package.json"
workingDir = file("${project.projectDir}/src/main/resources/static")
args = ['install']
}

Here I am defining a new task (enhanced task), that is of type NpmTask (defined in gradle-node-plugin) then set some properties (defined by the parent task (NpmTask) ), so it can do the job.

so, now I can run: gradle my_npm_task and gradle now will run npm install against the correct package.json file.

What is remaining is to have the this task run after I run gradle build (the build task).

Thanks to the amazing tasks dependency feature provided by gradle, I can refer to some task (provided by java plugin - I think) and make it depends on another task (the one I wrote).

Like this: build.dependsOn(my_npm_install)

Then when I run gradle build, here's the output:

.....
......

So that, the build task will run my_npm_install: (here's the output of gradle build command):

:check
:nodeSetup SKIPPED
:my_npm_install
:build
.......
......

gradle run the my_npm_install task before the build task.

Again, gradle is much more powerful and flexible than maven, and have a better syntax as well.
 

13 September 2016

Rename tv series movies files and subtitles to match

I wrote a simple script to rename the tv series files and its subtitles and remove all extract characters but the episode number along with the extension so the media players (such as VLC) can assign the subtitles automatically.

https://gist.github.com/MuhammadHewedy/a23225acc389e25d393df4659123b880