Power Assert for Java and others


Peter Niederwieser, creator of Spock, the best testing framework ever, also contributed to Groovy programming language a very handy feature: Power Asserts.

int x = 1;
assert x == 2;

// Output:             
//
// Assertion failed:
// assert x == 2
//        | |
//        1 false

As you can see, we can see each value of each statement, and this is very cool, especially for unit tests.
It makes all this JUnit bullshit like assertEquals(), assertTrue, assertNull, and all matchers like Hamcrest absolutely unneeded.
I really hate all matchers like FEST or Hamcest, because they aren’t natural and repeat code itself.

So now you can breathe freely without any repeating yourself.

You can see a talk where Peter Niederwieser present Spock specifications

Also Peter created Power Asserts lib for Scala
https://github.com/pniederw/expecty

But,
Unfortunately, you can’t make a Power Asserts in Java, because it doesn’t have a AST preprocessor.

If you, like me, have a big project with tests written in Java+JUnit, the only one way that I found, is convert them to Groovy (in 99% just change file extension from Java to Groovy) or you can compile your tests with groovyc — it’s Groovy Compiler but compiles Java too as well.
After compiling with groovyc asserts in Java behaves like in Groovy. Maybe this is the only one case when something written in Java works differently when compiled with Groovy.

For example here is simple test in Java

import org.junit.Test

class UserTest {
    @Test
    public void testName() {
        String username = "olololo";
        assert username.equals("trololo");
    }

}

After compiling with groovyc it’s decompiled bytecode will looks like:

// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
import org.codehaus.groovy.runtime.powerassert.AssertionRenderer;
import org.codehaus.groovy.runtime.powerassert.ValueRecorder;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
import org.junit.Test;

public class UserTest implements GroovyObject {
    public UserTestGroovy() {
        CallSite[] var1 = $getCallSiteArray();
        MetaClass var2 = this.$getStaticMetaClass();
        this.metaClass = var2;
    }

    @Test
    public void testName() {
        CallSite[] var1 = $getCallSiteArray();
        String username = "olololo";
        ValueRecorder var3 = new ValueRecorder();

        try {
            CallSite var10000 = var1[0];
            var3.record(username, 8);
            Object var6 = var10000.call(username, "trololo");
            var3.record(var6, 17);
            if(DefaultTypeTransformation.booleanUnbox(var6)) {
                var3.clear();
            } else {
                ScriptBytecodeAdapter.assertFailed(AssertionRenderer.render("assert username.equals(\"trololo\")", var3), (Object)null);
            }

        } catch (Throwable var5) {
            var3.clear();
            throw var5;
        }
    }
}

As you can see, it uses ValueRecorder to store all evaluated expressions and it will render a source code line. And it may be executed as class file (may require groovy-all dependency in classpath):

Assertion failed: 

assert username.equals("trololo")
       |        |
       olololo  false

	at org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:402)
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.assertFailed(ScriptBytecodeAdapter.java:650)
	at com.github.stokito.UserTest.testName(UserTest.java:9)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)

Unfortunately currently IntelliJ can’t compile Java files with Groovyc. It always compiles *.java files with javac.
I created an issue Allow groovyc as compiler for Java classes, please vote for it.

Power Asserts in other languages

Kotlin

does not exist but authors know about Power Assertions and had intentions to do them.

.NET languages

https://github.com/PowerAssert/PowerAssert.Net

JavaScript

https://github.com/power-assert-js/power-assert
https://github.com/power-assert-js/espower-typescript for TypeScript
https://github.com/power-assert-js/espower-babel
https://github.com/power-assert-js/babel-plugin-espower
https://github.com/twada/battlefield-sourcemaps
https://github.com/deepblue-will/coffee-power-assert for Cofee Script
https://github.com/twada/fly-espower

Ruby

There is a gem https://github.com/k-tsj/power_assert and here is presentation from author:

https://github.com/joker1007/rspec-power_assert
https://rubygems.org/gems/power_assert/versions/0.2.4
https://github.com/hsbt/minitest-power_assert
https://github.com/yui-knk/pry-power_assert for Pry REPL

Others

https://github.com/keygx/PAssert XCTest by Swift
https://github.com/rosylilly/power_assert.cr for Crystal (static Ruby)
https://github.com/ma2gedev/power_assert_ex for Elixir
https://github.com/gifnksm/power-assert-rs for Rust
https://github.com/haya14busa/vital-power-assert for Vim script

TODO: write about power assets in https://en.wikipedia.org/wiki/Assertion_(software_development)

Реклама

4 comments

  1. Уведомление: Spock or not to Spock? | stokito on software
  2. Уведомление: Power Assert for Java and other languages – Full-Stack Feed
  3. Уведомление: Power Assert for Java and other languages | gtgbusiness1

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s