Never debug a test again: Detailed failure reports and hassle free assertions for Java tests - Power Asserts for Java

Overview

License Maven Central Build Status Quality Gate Status

Scott Test Reporter for Maven and Gradle

Get extremely detailed failure messages for your tests without assertion libraries, additional configuration or changes on existing tests.

Scott in Action

As you can see, besides the usual assertion error, Scott reports the state changes and assignments in the test cases, nicely visualized on the source code of the test method.

Works well with other testing tools and frameworks, for example:

Supports Java 7+ (up to Java 17).

How to use

Just drop it into your project, and Scott will automatically enhance your test reports. You don't have to use any special APIs or modify your existing tests to make it work.

Scott: All systems automated and ready. A chimpanzee and two trainees could run her.

Kirk: Thank you, Mr. Scott. I'll try not to take that personally.

Gradle

Add hu.advanceweb.scott-gradle-plugin to your build.gradle:

plugins {
  id "hu.advanceweb.scott-gradle-plugin" version "4.0.1"
}

Example projects:

Maven

Add the following to your pom.xml:

<build>
	<plugins>
		<!-- Add the Scott Plugin. -->
		<plugin>
			<groupId>hu.advancedweb</groupId>
			<artifactId>scott-maven-plugin</artifactId>
			<version>4.0.1</version>
			<executions>
				<execution>
					<goals>
						<goal>prepare-agent</goal>
					</goals>
				</execution>
			</executions>
		</plugin>
	</plugins>
</build>
<dependencies>
	<!-- Add Scott as a dependency -->
	<dependency>
		<groupId>hu.advancedweb</groupId>
		<artifactId>scott</artifactId>
		<version>4.0.1</version>
		<scope>test</scope>
	</dependency>
</dependencies>

The scott-maven-plugin automatically configures maven-surefire-plugin and maven-failsafe-plugin to use Scott via the argLine project property. If you wish to further customize the argLine property for these plugins, you have to pass the managed argLine as well to ensure Scott works properly. For an example, check the following snippet that configures the surefire plugin to enable preview language features for Java:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <argLine>${argLine} --enable-preview</argLine>
    </configuration>
</plugin>

Example projects:

Cucumber

Scott for Cucumber tracks whole scenarios, and in case of a failure it prints the details of every step involved.

This feature provides valuable information if a test fails in a CI environment, as it can make it much easier to reproduce and fix browser-based tests, especially for flaky tests.

HTML

Example project:

Wire it up manually

If you can't use the Gradle or Maven Plugin for some reason, you can do the necessary integration steps manually.

Configuration

In case you are not satisfied with the default tracking behavior, the Scott Maven Plugin and Gradle Plugin provides configuration options to fine-tune its behaviour.

Using Scott as an instrumentation library

Scott's instrumentation module can be invoked programmatically with fine-tuned instrumentation rules so you can build your own solution on top of Scott. For more information, check the user guide, and for an actual example, see GhostWriter.

Changelog

See Releases.

Highlights from the latest releases:

Contributing

Contributions are welcome! Please make sure to visit the contribution and development guide for some important notes on how to build and debug Scott. If you are looking for issues that can get you started with the development, see Issues marked with the help-wanted tag.

Comments
  • https://github.com/damianszczepanik/cucumber-reporting

    https://github.com/damianszczepanik/cucumber-reporting

    This will solve the ticket Record whole scenarios with Cucumber #12

    in addition to

    • html
    • console
    • json
    • i added a plugin that will generate also html based on the json file, to the verification becomes more easy (https://github.com/damianszczepanik/cucumber-reporting)
    Hacktoberfest 
    opened by basalt79 10
  • Add test for Local Variable Type Inference

    Add test for Local Variable Type Inference

    Enhance the test suite to verify that variables in tests containing var keywords are correctly recorded. Similar tests can be found in the junit4-tests project. For more info about Local Variable Type Inference, see JEP 286 and JEP 323.

    Also, add a failing test to the showcase project, to make sure that the rendered failure message looks pretty.

    Note: please make sure to visit the contribution and development guide for some important notes on how to build and debug Scott.

    help wanted Hacktoberfest good first issue 
    opened by dodie 9
  • Improve loop rendering

    Improve loop rendering

    When a loop body is executed multiple times, Scott records and prints variable states from every turn:

      47|      @Test
      48|      public void test() throws Exception {
      49|          int i = 0;  // i=0
      50|          while (i < 10) {
      51|              i = i + 1;  // i=1
        |                          // i=2
        |                          // i=3
        |                          // i=4
        |                          // i=5
        |                          // i=6
        |                          // i=7
        |                          // i=8
        |                          // i=9
        |                          // i=10
      52|          }
      53|*         fail();  // AssertionError
      54|      }
    

    This looks really boring, and should be enhanced.

    Maybe print the first and the last few only with the number of the corresponding turn; or simply show the last recorded value?

    enhancement help wanted rendering Hacktoberfest 
    opened by dodie 9
  • Support for Mockito

    Support for Mockito

    Currently, Mockito fails while stubbing as scott tries to call toString while mockito is capturing method calls. This could be partially resolved with a check in hu.advancedweb.scott.runtime.track.StateRegistry#objectToString:

    	//...
    	} else if (MockUtil.isMock(value)) {
    		// While setting up mocks with when(...), invoking any method on the mock will
    		// cause it to be recorded thus breaking the when() statement.
    		return constructMockitoMockObjectString(value);
    	}else if (MockUtil.isSpy(value)){
    		return "Mockito Spy:" + MockUtil.getMockName(value);
    	}	//...
    
    	public static String constructMockitoMockObjectString(Object value){
    		return "Mockito Mock("+ MockUtil.getMockSettings(value).getTypeToMock()+")";
    	}
    

    Along with the required dependency:

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>2.2.28</version>
        </dependency>
    

    But it still doesn't solve the case where method calls are inlined when stubbing.

    bug recording integration 
    opened by tom91136 8
  • Stream.anyMatch causes NoClassDefFoundError: hu/advancedweb/scott/runtime/track/StateRegistry

    Stream.anyMatch causes NoClassDefFoundError: hu/advancedweb/scott/runtime/track/StateRegistry

    While test driving scott, I've encountered a rather strange exception. If I use Stream.anyMatch, for example:

    new ArrayList<String>().stream().anyMatch(s -> false);
    

    A NoClassDefFoundError is thrown for some reason. I've checked scott's source but can't really find anything as I'm not familiar with java instrumentation. Perhaps you can give me some pointers as I'm really impressed with scott and would like to contribute.

    The stacktrace:

    java.lang.Error:
       0|* ???  // NoClassDefFoundError: hu/advancedweb/scott/runtime/track/StateRegistry
       // removed , my source 
            at hu.advancedweb.scott.runtime.ScottReportingRule$1.evaluate(ScottReportingRule.java:30)
            at org.junit.rules.RunRules.evaluate(RunRules.java:20)
            at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
            at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
            at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
            at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
            at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
            at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
            at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
            at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
            at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
            at org.junit.runners.Suite.runChild(Suite.java:128)
            at org.junit.runners.Suite.runChild(Suite.java:27)
            at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
            at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
            at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
            at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
            at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
            at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
            at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
            at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
            at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
            at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
            at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
            at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
            at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
            at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
    Caused by: java.lang.NoClassDefFoundError: hu/advancedweb/scott/runtime/track/StateRegistry
            at java.util.stream.MatchOps.lambda$makeRef$0(MatchOps.java:97)
            at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
            at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
            at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
            at java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:449)
           
    	     // stuff that makes call to anyMatch...
    	   
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
            at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
            at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
            at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
            at hu.advancedweb.scott.runtime.ScottReportingRule$1.evaluate(ScottReportingRule.java:26)
            ... 31 more
    
    bug recording 
    opened by tom91136 7
  • Integrate the project into a continuous integration solution

    Integrate the project into a continuous integration solution

    Hey Dávid!

    I was wondering if you have plans for integrating the project into a continuous integration system, like Travis CI. Based on the contribution guide, I guess you can include steps like:

    • building and testing the core Scott module (mvn clean install). I believe a setup in Travis CI would be very easy to implement: https://docs.travis-ci.com/user/languages/java/
    • maybe you can even build and test the Gradle plugin? I'm not yet sure on the project setup. :/
    • add a static analysis solution, e.g. Sonar or Codacy. I have little experience with Codacy, but integration for open source repos is pretty easy to do. Probably worth a try.

    Values I see in this change:

    • first and foremost valuable feedback for you after commits, even if you are the only developers.
    • helps the contribution flow. If you agree with the toolings, automating static analysis should help speed up the reviews.
    • the green badge on the README representing the successful build always looks nice. :)

    Let me know what you think! Cheers, Balázs

    build 
    opened by hosszubalazs 5
  • Add test for try-with-resources statement

    Add test for try-with-resources statement

    Enhance the test suite to verify that variables in tests containing try-with-resource statements are correctly recorded. Similar tests can be found in the junit4-tests project.

    Also, add a failing test to the showcase project, to make sure that the rendered failure message looks pretty.

    Note: please make sure to visit the contribution and development guide for some important notes on how to build and debug Scott.

    help wanted Hacktoberfest good first issue 
    opened by dodie 5
  • Invalid bytecode for instrumenting method with branches and a try-finally

    Invalid bytecode for instrumenting method with branches and a try-finally

    Issue #57 fixed a weird issue with first label vs first instruction order, that affects some environments.

    It seems that the fix was only implemented in the ScopeExtractorMethodVisitor, but it also affects the StateTrackingMethodVisitor.

    In this case the symtom is not a runtime error while instrumenting, but it causes an invalid trace call to be injected which results in invalid bytecode.

    bug recording 
    opened by dodie 4
  • Gradle plugin

    Gradle plugin

    Issue #44

    Please read https://guides.gradle.org/publishing-plugins-to-gradle- plugin-portal /

    After configuring your credentials you can publish the plugin locale at scott-gradle-plugin folder

    $ ./gradlew tasks

    Plugin Portal tasks
    -------------------
    login - Update the gradle.properties files so this machine can publish to the Gradle Plugin portal.
    **publishPlugins - Publishes this plugin to the Gradle Plugin portal.**
    

    $ ./gradlew publishPlugins

    > Task :publishPlugins
    Publishing plugin hu.advanceweb.scott-plugin version 3.3.3
    Publishing artifact build/libs/gradle-3.3.3.jar
    Publishing artifact build/libs/gradle-3.3.3-sources.jar
    Publishing artifact build/libs/gradle-3.3.3-javadoc.jar
    Publishing artifact build/libs/gradle-3.3.3-groovydoc.jar
    Publishing artifact build/publish-generated-resources/pom.xml
    Activating plugin hu.advanceweb.scott-plugin version 3.3.3
    

    To test/approve the PR, I believe you can follow those flow to generate the artifacts and test the changes.

    The Junit4 and Junit5 test reports keep detailed information, but only cucumber reports generated by scott.

    :brazil:

    opened by luksrn 4
  • Show differences

    Show differences

    @Test
    public void test_3() {
        String empty = "";
        String first = "1";
        String last = "2";
        String concatenated = empty + first + last;
        assertEquals(12, concatenated);
    }
    

    will lead to

    java.lang.AssertionError: 
      29|      @Test
      30|      public void test_3() {
      31|          String empty = "";  // empty=
      32|          String first = "1";  // first=1
      33|          String last = "2";  // last=2
      34|          String concatenated = empty + first + last;  // concatenated=12
      35|*         assertEquals(12, concatenated);  // AssertionError: expected: java.lang.Integer<12> but was: java.lang.String<12>
      36|      }
     <Click to see difference>
    

    after click "Click to see difference" link at Intellij, the diff will be reported as

    view_difference

    as you can see, there is also the " 36| }" shown as difference

    bug wontfix 
    opened by basalt79 4
  • Record whole scenarios with Cucumber

    Record whole scenarios with Cucumber

    For a failing step in the Cucumber Example, only the failing step definition gets printed. It would be nice if the previous steps would be rendered as well for the failing scenario.

    enhancement integration Hacktoberfest 
    opened by dodie 4
  • Automate release

    Automate release

    Regular maintenance requires many manual steps:

    • Bump asm and javaparser dependencies to ensure that Scott can work with the latest Java.
    • Bump ASM constant in the visitors. (E.g. ASM7->ASM8)
    • Modify JUnit5 tests and build pipelines to run with latest Java
    • Add new tests for some new Java features
    • Run all test suites
    • Release a new version (doc), including:
      • Bump versions
      • Release artifacts to Maven Central
        • Upload artifacts
        • Manually approve staged artifacts on the Nexus UI
      • Release Gradle Plugin
      • Update version references in the documentation

    Ideally, parts of this process should be handled by build pipelines.

    build 
    opened by dodie 3
Releases(4.0.1)
  • 4.0.1(Sep 29, 2021)

  • 4.0.0(Sep 24, 2021)

    New features:

    • Support Java 17 #109

    Fixes:

    • No more warnings about illegal reflective access #43

    Removal:

    • ScottRunListener for JUnit4 is removed: this alternative reporting integration was not used, and was not compatible with Java 17.
    • Support for info.cukes:cucumber-java is removed: this library is no longer maintained, and does not support Java 17. It is superseded by io.cucumber:cucumber-java which is still supported.
    Source code(tar.gz)
    Source code(zip)
  • 3.6.0(Nov 12, 2019)

  • 3.5.0(Jul 10, 2019)

    New features:

    • Java API: Scott's instrumentation module can be invoked programmatically with fine-tuned instrumentation rules so you can build your own solution on top of Scott. For more information, check the user guide.

    Fixes:

    • Invalid bytecode for instrumenting method with branches and a try-finally #80
    Source code(tar.gz)
    Source code(zip)
  • 3.4.1(Jan 7, 2019)

  • 3.4.0(Dec 4, 2018)

    New features:

    • Gradle Plugin #44 . See this guide for configuration options.
    • Java 11 and Java 12 Support #47 #77
    • Support for io.cucumber:cucumber-java #45 . See the example project.

    Fixes:

    • Scott now calculates local variable scopes based on labels, instead of line numbers. This fixes some issues with tests using try-with-resources or unusual formatting. #46, #19
    Source code(tar.gz)
    Source code(zip)
  • 3.3.0(Jan 21, 2018)

  • 3.2.0(Jan 21, 2018)

  • 3.1.0(Oct 17, 2017)

    New features:

    • Maven Plugin #4
    • Scott Cucumber JVM now records whole scenarios #12
    • Improved loop rendering #18
    • Improved string appearance #27

    Also, from this release the project has an example project for the release version of JUnit5 #37

    Source code(tar.gz)
    Source code(zip)
  • 3.0.0(May 20, 2017)

    New features:

    • JUnit 5 Support #24
    • Support for Mockito #25

    Breaking change: Due to the added JUnit 5 support the optional config params have been changed. Scott can be configured with the following parameters:

    • scott.track.method_annotation
    • scott.inject_junit4_rule.method_annotation
    • scott.inject_junit5_rule.method_annotation
    Source code(tar.gz)
    Source code(zip)
  • 2.0.1(Nov 25, 2016)

    Bugfixes:

    • Stream.anyMatch causes NoClassDefFoundError: hu/advancedweb/scott/runtime/track/StateRegistry #22
    • Input parameters of one-line lambdas are rendered at the wrong place #23
    Source code(tar.gz)
    Source code(zip)
  • 2.0.0(Oct 29, 2016)

    New features:

    • Record values in lambda expressions #11
    • Render method input parameters #10
    • Record field mutation and access #13
    • Enhanced error reporting #16
    • Support tests in directories other than src/test #6
    • Provide instrumentation configuration #7
    • Add Cucumber example / support #8
    • Automatically inject ScottReportingRule to test classes #3

    Bugfixes:

    • Repackage dependent libraries to avoid classpath collisions #20
    • Variable names are not recorded in for blocks #17
    • Fix boolean value recording #1
    • Record the name of a variable, even if its declaration is the last statement in a block #15
    • Block with a single declaration breaks instrumentation #2
    • Variable scopes in Try blocks has wrong end Label #14
    • Fix multiline exception message rendering #9
    Source code(tar.gz)
    Source code(zip)
🤖 Unleash the full power of test.ai into your Java Appium tests

The test.ai Appium SDK is a simple library that makes it easy to write robust cross-platform mobile application tests backed by computer vision and ar

test.ai 9 Jun 4, 2022
Fluent assertions for Java and Android

What is Truth? Truth makes your test assertions and failure messages more readable. Similar to AssertJ, it natively supports many JDK and Guava types,

Google 2.6k Jan 5, 2023
Utility to automatically manage all web element waits and enables to write wait-free selenium tests.

selenium-auto-wait selenium-auto-wait automatically manages all weblement waits and makes you to write wait free selenium tests. Features Waits till e

Sudharsan Selvaraj 31 Nov 1, 2022
Fluent assertions library for Java

Deep Dive Assertions Deep Dive is an assertion library for Java. It offers a fluent API which allows you to dive deep, i.e. going back and forth betwe

Johannes Döbler 6 Jan 24, 2022
AssertJ is a library providing easy to use rich typed assertions

AssertJ - Fluent assertions for java AssertJ provides a rich and intuitive set of strongly-typed assertions to use for unit testing (with JUnit, TestN

AssertJ 2.3k Dec 30, 2022
AssertJ is a library providing easy to use rich typed assertions

AssertJ - Fluent assertions for java AssertJ provides a rich and intuitive set of strongly-typed assertions to use for unit testing (with JUnit, TestN

AssertJ 2.3k Jan 8, 2023
PGdP-Tests-WS21/22 is a student-created repository used to share code tests.

PGdP-Tests-WS21-22 PGdP-Tests-WS21/22 is a student-created repository used to share code tests. Important Note: In the near future, most exercises wil

Jonas Ladner 56 Dec 2, 2022
Serenity BDD is a test automation library designed to make writing automated acceptance tests easier, and more fun.

That feeling you get when you know you can trust your tests Serenity BDD is a library designed to make writing automated acceptance tests easier, and

Serenity BDD 654 Dec 28, 2022
A sample repo to help you handle basic auth for automation test in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to handle basic auth for automation test in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Windows - htt

null 12 Jul 13, 2022
A sample repo to help you run automation test in incognito mode in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to run automation test in incognito mode in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Windows - htt

null 12 Jul 13, 2022
A sample repo to help you handle cookies for automation test in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to handle cookies for automation test in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Windows - https:

null 13 Jul 13, 2022
A sample repo to help you set geolocation for automation test in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to set geolocation for automation test in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Windows - https

null 12 Jul 13, 2022
A sample repo to help you capture JavaScript exception for automation test in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to capture JavaScript exception for automation test in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Wi

null 12 Jul 13, 2022
A sample repo to help you find an element by text for automation test in Java-selenium on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to find an element by text for automation test in Java-selenium on LambdaTest Prerequisites Install and set environment variable for java. Windows

null 12 Jul 13, 2022
A sample repo to help you emulate network conditions in Java-selenium automation test on LambdaTest. Run your Java Selenium tests on LambdaTest platform.

How to emulate network conditions in Java-selenium automation test on LambdaTest Prerequisites Install and set environment variable for java. Windows

null 12 Jul 13, 2022
Arbitrary test data generator for parameterized tests in Java inspired by AutoFixture.

AutoParams AutoParams is an arbitrary test data generator for parameterized tests in Java inspired by AutoFixture. Sometimes setting all the test data

null 260 Jan 2, 2023
A sample repo to help you capture JavaScript exception for automation test in Java-TestNG on LambdaTest. Run Selenium tests with TestNG on LambdaTest platform.

How to capture JavaScript exception for automation test in Java-TestNG on LambdaTest Environment Setup Global Dependencies Install Maven Or Install Ma

null 11 Jul 13, 2022
A sample repo to help you use relative locators for automation test in Java-TestNG on LambdaTest. Run Selenium tests with TestNG on LambdaTest platform.

How to use relative locators for automation test in Java-TestNG on LambdaTest Environment Setup Global Dependencies Install Maven Or Install Maven wit

null 11 Jul 13, 2022