SlideShare a Scribd company logo
1 of 25
Download to read offline
Advanced Java Testing
What’s next?
Vincent Massol, February 2018
Agenda
•Context & Current status quo
•Coverage testing
•Testing for backward compatibility
•Mutation testing
•Environment testing
Context: XWiki
• Open source wiki
• 14 years
• 10-15 active committers
• Very extensible, scripting in wiki pages
• Platform for developing ad-hoc web applications
• Strong build practices using Maven and lots of “Quality” plugins
• Using Jenkins & custom pipeline library for the CI
http://xwiki.org
Context: STAMP
• Automatic Test Amplification
• XWiki SAS participating
• Experiment on XWiki project
Mutation testing Environment Testing
Current Testing Status
• 10414 automated tests (in 2.5 hours):
• Unit tests (using Mockito)
• Integration tests (using Mockito)
• Functional (UI) tests (using Selenium/Webdriver)
New questions
• Are my tests testing enough? Coverage
• How can I prevent breaking my users (when I
expose some APIs)? Backward compatibility
• How good are my tests? Mutation testing
• Do my software work in various setups?
Environment testing
= in place w/ strategy = in progress
Test Coverage
• Using Jacoco and Clover
• Strategy - “Ratchet effect”:
• Each Maven module has a threshold
• Jacoco Maven plugin fails if new code
has less coverage than before in %
• Dev is allowed to increase threshold
• Global Clover TPC computed
automatically once per month on
Jenkins for all repos combined
Source: http://massol.myxwiki.org/xwiki/bin/view/Blog/ComparingCloverReports
2016-12-20
2017-11-09
+1.9%
Harmonized TPC
Of course TPC is not panacea. You
could have 100% and app not
working. Also need functional tests.
Aim for 80%.
Backward Compatibility
• For APIs (and SPIs)
• Using the Revapi Maven plugin
• Supports source and binary compatibility
• Strategy:
• Break the build on backward compatibility
violations
• Add ignores in pom.xml if really needed
and ok
• Add ignore list in release notes to warn
users of your APIs
Backward Compatibility
• Strategy continued:
• Use @Deprecated annotation
• Once no more code uses deprecated API, move it to Legacy
module.We don’t break backward compatibility!
• Use AspectJ in Legacy module to generate and aspectified
API (JAR)
• Makes code clean and not able to use the Legacy modules
(build-enforced)
• Distribute the legacy modules
public privileged aspect ApiCompatibilityAspect
{
@Deprecated
public boolean Api.checkProgrammingRights()
{
return this.hasProgrammingRights();
}
}
Java 8 default methods helped a lot
Backward Compatibility
• Strategy continued:
• For young APIs, use @Unstable + @Since
• Enforced by build (to make sure @Since is there).
Custom checkstyle rule (or Spoon rule)
• Max duration is one cycle (i.e. 1 year).
• Enforced by build (fails the build if beyond).
/**
* ...
* @since 9.7RC1
*/
@Unstable
public List<MacroDescriptor> getMacroDescriptors(Syntax syntax) throws MacroLookupException
{
...
}
Mention that as a result XWiki
extensions and scripts can still run in
XWiki even several years after they
were released.
Mutation Testing
• Using PIT and Descartes
• Concepts
• Modify code under test (mutants) and run tests
• Good tests kill mutants
• Generates a mutation score similar to the coverage %
• Descartes = extreme mutations that execute fast and have high
values
Mutation - Descartes
Mutation - Example
Mutation - Example
result =
   (getId() == macroId.getId() || (getId() != null && getId().equals(macroId.getId())))
   && (getSyntax() == macroId.getSyntax() || (getSyntax() != null && getSyntax().equals(
    macroId.getSyntax())));
Mutation - Example
@Test
public void testEquality()
{
    MacroId id1 = new MacroId("id", Syntax.XWIKI_2_0);
    MacroId id2 = new MacroId("id", Syntax.XWIKI_2_0);
    MacroId id3 = new MacroId("otherid", Syntax.XWIKI_2_0);
    MacroId id4 = new MacroId("id", Syntax.XHTML_1_0);
    MacroId id5 = new MacroId("otherid", Syntax.XHTML_1_0);
    MacroId id6 = new MacroId("id");
    MacroId id7 = new MacroId("id");
    Assert.assertEquals(id2, id1);
   // Equal objects must have equal hashcode
   Assert.assertTrue(id1.hashCode() == id2.hashCode());
    Assert.assertFalse(id3 == id1);
    Assert.assertFalse(id4 == id1);
    Assert.assertFalse(id5 == id3);
    Assert.assertFalse(id6 == id1);
    Assert.assertEquals(id7, id6);
   // Equal objects must have equal hashcode
   Assert.assertTrue(id6.hashCode() == id7.hashCode());
}
Not testing
for inequality!
Improved thanks to Descartes!
Mutation - Limitations
• Takes time to find interesting things to look at and decide if that’s an
issue to handle or not. Need better categorisation in report:
• Strong pseudo-tested methods:The worst! No matter what the
return values are the tests always fail
• Pseudo-tested methods: Grey area.The tests pass with at least one
modified value.
• Multi module support - PITmp
• Slow on large projects (e.g. 7+ hours just for xwiki-rendering)
Mutation - Strategy
• Work in progress, no feedback yet!
• Fail the build when the mutation score of a given module is below
a defined threshold in the pom.xml
• The idea is that new tests should, in average, be of quality equal or
better than past tests.
• Other idea: hook on CI to run it only on modified code/tests.
Ideally: replace coverage check by mutation check(*)
(*) But too slow for now to replace coverage, can be done in addition (in a Maven profile for example,
or executed on CI).Timeouts are a problem for example.
Mutation: Going further
• Using DSpot
• Uses PIT/Descartes but injects results to generate new
tests
• Adds assertions to existing tests
• Generate new test methods
Mutation: Dspot Example
public void escapeAttributeValue2() {
String escapedText = XMLUtils.escapeAttributeValue("a < a' && a' < a" => a < a" {");
// AssertGenerator add assertion
Assert.assertEquals("a &#60; a&#39; &#38;&#38; a&#39; &#60; a&#34; =&#62; a &#60; a&#34; &#123;", escapedText);
// AssertGenerator create local variable with return value of invocation
boolean o_escapeAttributeValue__3 = escapedText.contains("<");
// AssertGenerator add assertion
Assert.assertFalse(o_escapeAttributeValue__3);
// AssertGenerator create local variable with return value of invocation
boolean o_escapeAttributeValue__4 = escapedText.contains(">");
// AssertGenerator add assertion
Assert.assertFalse(o_escapeAttributeValue__4);
// AssertGenerator create local variable with return value of invocation
boolean o_escapeAttributeValue__5 = escapedText.contains("'");
// AssertGenerator add assertion
Assert.assertFalse(o_escapeAttributeValue__5);
// AssertGenerator create local variable with return value of invocation
boolean o_escapeAttributeValue__6 = escapedText.contains(""");
// AssertGenerator create local variable with return value of invocation
boolean o_escapeAttributeValue__7 = escapedText.contains("&&");
// AssertGenerator add assertion
Assert.assertFalse(o_escapeAttributeValue__7);
// AssertGenerator create local variable with return value of invocation
boolean o_escapeAttributeValue__8 = escapedText.contains("{");
// AssertGenerator add assertion
Assert.assertFalse(o_escapeAttributeValue__8);
}
Generated test
New test
@Test
public void escapeAttributeValue()
{
String escapedText = XMLUtils.escapeAttributeValue("a < a' && a' < a" => a < a" {");
assertFalse("Failed to escape <", escapedText.contains("<"));
assertFalse("Failed to escape >", escapedText.contains(">"));
assertFalse("Failed to escape '", escapedText.contains("'"));
assertFalse("Failed to escape "", escapedText.contains("""));
assertFalse("Failed to escape &", escapedText.contains("&&"));
assertFalse("Failed to escape {", escapedText.contains("{"));
}
Original test
Mutation: Dspot Strategy
• DSpot is very slow to execute.
• One strategy is to run it on CI from time to time and
in the pipeline commit generated tests in a different
source root.
• Configure Maven to add a new test directory source
using the Maven Build Helper plugin.
• Another idea: run it as GitHub commit hook so that it
only executed on the modified code.
Environment Testing
• Environment = combination of Servlet
container & version, DB & version, OS,
Browser & version, etc
• Using Docker
• Need: Be able to run functional tests on
local dev machines as well as on CI
• Lead to using Fabric8 Docker Maven
Plugin (DMP)
Environment Testing
- One maven module to generate the XWiki Docker image for the official distribution

- Another maven module to generate the XWiki Maven Docker image (Maven +
Browsers installed)

- In each functional test module, use the DMP to start the DB Docker image + the
XWiki image + the XWiki Maven image.

- Execute Maven’s verify goal inside the XWiki Maven image
Parting words
• Experiment, push the limit!
• Some other types of tests not covered and that also need
automation
• Performance/Stress testing
• Usability testing
• others?
Q&A
Me
Vincent Massol
vincent@xwiki.com
skype: vmassol
http://about.me/vmassol
http://xwiki.org
http://xwiki.com

More Related Content

What's hot

Powershell_Basics_Robin
Powershell_Basics_RobinPowershell_Basics_Robin
Powershell_Basics_Robin
Robin Aggarwal
 
Metrics 2.0 @ Monitorama PDX 2014
Metrics 2.0 @ Monitorama PDX 2014Metrics 2.0 @ Monitorama PDX 2014
Metrics 2.0 @ Monitorama PDX 2014
Dieter Plaetinck
 

What's hot (20)

Fetch data from form
Fetch data from formFetch data from form
Fetch data from form
 
Linq
LinqLinq
Linq
 
Mssql to mysql - Anton Ivanov
Mssql to mysql - Anton IvanovMssql to mysql - Anton Ivanov
Mssql to mysql - Anton Ivanov
 
The Ring programming language version 1.9 book - Part 74 of 210
The Ring programming language version 1.9 book - Part 74 of 210The Ring programming language version 1.9 book - Part 74 of 210
The Ring programming language version 1.9 book - Part 74 of 210
 
Alexey Golub - Dependency absolution (application as a pipeline) | Svitla Sma...
Alexey Golub - Dependency absolution (application as a pipeline) | Svitla Sma...Alexey Golub - Dependency absolution (application as a pipeline) | Svitla Sma...
Alexey Golub - Dependency absolution (application as a pipeline) | Svitla Sma...
 
Sbt for mere mortals
Sbt for mere mortalsSbt for mere mortals
Sbt for mere mortals
 
The Groovy Way of Testing with Spock
The Groovy Way of Testing with SpockThe Groovy Way of Testing with Spock
The Groovy Way of Testing with Spock
 
Streaming Data with scalaz-stream
Streaming Data with scalaz-streamStreaming Data with scalaz-stream
Streaming Data with scalaz-stream
 
Icinga2 api use cases
Icinga2 api use casesIcinga2 api use cases
Icinga2 api use cases
 
Event-Driven Systems With MongoDB
Event-Driven Systems With MongoDBEvent-Driven Systems With MongoDB
Event-Driven Systems With MongoDB
 
Sprint 70
Sprint 70Sprint 70
Sprint 70
 
Sprint 69
Sprint 69Sprint 69
Sprint 69
 
Python in the database
Python in the databasePython in the database
Python in the database
 
Cassandra Day Denver 2014: Building Java Applications with Apache Cassandra
Cassandra Day Denver 2014: Building Java Applications with Apache CassandraCassandra Day Denver 2014: Building Java Applications with Apache Cassandra
Cassandra Day Denver 2014: Building Java Applications with Apache Cassandra
 
Tutorial - 16 : How to pass parameters from one script to another by CallScri...
Tutorial - 16 : How to pass parameters from one script to another by CallScri...Tutorial - 16 : How to pass parameters from one script to another by CallScri...
Tutorial - 16 : How to pass parameters from one script to another by CallScri...
 
Powershell_Basics_Robin
Powershell_Basics_RobinPowershell_Basics_Robin
Powershell_Basics_Robin
 
Cassandra Day Chicago 2015: Building Java Applications with Apache Cassandra
Cassandra Day Chicago 2015: Building Java Applications with Apache CassandraCassandra Day Chicago 2015: Building Java Applications with Apache Cassandra
Cassandra Day Chicago 2015: Building Java Applications with Apache Cassandra
 
Realm database
Realm databaseRealm database
Realm database
 
Android getting started
Android getting startedAndroid getting started
Android getting started
 
Metrics 2.0 @ Monitorama PDX 2014
Metrics 2.0 @ Monitorama PDX 2014Metrics 2.0 @ Monitorama PDX 2014
Metrics 2.0 @ Monitorama PDX 2014
 

Similar to Advanced Java Testing

谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testability谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testability
drewz lin
 
Cerberus_Presentation1
Cerberus_Presentation1Cerberus_Presentation1
Cerberus_Presentation1
CIVEL Benoit
 

Similar to Advanced Java Testing (20)

New types of tests for Java projects
New types of tests for Java projectsNew types of tests for Java projects
New types of tests for Java projects
 
New types of tests for Java projects
New types of tests for Java projectsNew types of tests for Java projects
New types of tests for Java projects
 
Advanced Java Testing @ POSS 2019
Advanced Java Testing @ POSS 2019Advanced Java Testing @ POSS 2019
Advanced Java Testing @ POSS 2019
 
Junit_.pptx
Junit_.pptxJunit_.pptx
Junit_.pptx
 
Level Up Your Integration Testing With Testcontainers
Level Up Your Integration Testing With TestcontainersLevel Up Your Integration Testing With Testcontainers
Level Up Your Integration Testing With Testcontainers
 
Improve unit tests with Mutants!
Improve unit tests with Mutants!Improve unit tests with Mutants!
Improve unit tests with Mutants!
 
Mutation testing Bucharest Tech Week
Mutation testing Bucharest Tech WeekMutation testing Bucharest Tech Week
Mutation testing Bucharest Tech Week
 
JUnit5 and TestContainers
JUnit5 and TestContainersJUnit5 and TestContainers
JUnit5 and TestContainers
 
Building XWiki
Building XWikiBuilding XWiki
Building XWiki
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFX
 
Performance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle CoherencePerformance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle Coherence
 
Informix Java Driver Improvements 4.10.JC8
Informix Java  Driver Improvements 4.10.JC8Informix Java  Driver Improvements 4.10.JC8
Informix Java Driver Improvements 4.10.JC8
 
Unit testing with Spock Framework
Unit testing with Spock FrameworkUnit testing with Spock Framework
Unit testing with Spock Framework
 
谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testability谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testability
 
Testing basics for developers
Testing basics for developersTesting basics for developers
Testing basics for developers
 
Implementing Quality on a Java Project
Implementing Quality on a Java ProjectImplementing Quality on a Java Project
Implementing Quality on a Java Project
 
Migration strategies 4
Migration strategies 4Migration strategies 4
Migration strategies 4
 
Javazone 2019 - Mutants to the rescue: How effective are your unit tests?
Javazone 2019 - Mutants to the rescue: How effective are your unit tests?Javazone 2019 - Mutants to the rescue: How effective are your unit tests?
Javazone 2019 - Mutants to the rescue: How effective are your unit tests?
 
Cerberus : Framework for Manual and Automated Testing (Web Application)
Cerberus : Framework for Manual and Automated Testing (Web Application)Cerberus : Framework for Manual and Automated Testing (Web Application)
Cerberus : Framework for Manual and Automated Testing (Web Application)
 
Cerberus_Presentation1
Cerberus_Presentation1Cerberus_Presentation1
Cerberus_Presentation1
 

More from Vincent Massol

XWiki: wiki collaboration as an alternative to Confluence and Sharepoint
XWiki: wiki collaboration as an alternative to Confluence and SharepointXWiki: wiki collaboration as an alternative to Confluence and Sharepoint
XWiki: wiki collaboration as an alternative to Confluence and Sharepoint
Vincent Massol
 
Evolutions XWiki 2012/2013
Evolutions XWiki 2012/2013Evolutions XWiki 2012/2013
Evolutions XWiki 2012/2013
Vincent Massol
 

More from Vincent Massol (20)

XWiki Testing with TestContainers
XWiki Testing with TestContainersXWiki Testing with TestContainers
XWiki Testing with TestContainers
 
Configuration Testing with Docker & TestContainers
Configuration Testing with Docker & TestContainersConfiguration Testing with Docker & TestContainers
Configuration Testing with Docker & TestContainers
 
What's new in XWiki 9.x and 10.x
What's new in XWiki 9.x and 10.xWhat's new in XWiki 9.x and 10.x
What's new in XWiki 9.x and 10.x
 
QDashboard 1.2
QDashboard 1.2QDashboard 1.2
QDashboard 1.2
 
XWiki: wiki collaboration as an alternative to Confluence and Sharepoint
XWiki: wiki collaboration as an alternative to Confluence and SharepointXWiki: wiki collaboration as an alternative to Confluence and Sharepoint
XWiki: wiki collaboration as an alternative to Confluence and Sharepoint
 
XWiki: The web's Swiss Army Knife
XWiki: The web's Swiss Army KnifeXWiki: The web's Swiss Army Knife
XWiki: The web's Swiss Army Knife
 
Developing XWiki
Developing XWikiDeveloping XWiki
Developing XWiki
 
XWiki Status - July 2015
XWiki Status - July 2015XWiki Status - July 2015
XWiki Status - July 2015
 
XWiki SAS development practices
XWiki SAS development practicesXWiki SAS development practices
XWiki SAS development practices
 
XWiki SAS: An open source company
XWiki SAS: An open source companyXWiki SAS: An open source company
XWiki SAS: An open source company
 
XWiki: A web dev runtime for writing web apps @ FOSDEM 2014
XWiki: A web dev runtime for writing web apps @ FOSDEM 2014XWiki: A web dev runtime for writing web apps @ FOSDEM 2014
XWiki: A web dev runtime for writing web apps @ FOSDEM 2014
 
XWiki Rendering @ FOSDEM 2014
XWiki Rendering @ FOSDEM 2014XWiki Rendering @ FOSDEM 2014
XWiki Rendering @ FOSDEM 2014
 
Implementing Quality on Java projects (Short version)
Implementing Quality on Java projects (Short version)Implementing Quality on Java projects (Short version)
Implementing Quality on Java projects (Short version)
 
Implementing quality in Java projects
Implementing quality in Java projectsImplementing quality in Java projects
Implementing quality in Java projects
 
Implementing Quality on Java projects
Implementing Quality on Java projectsImplementing Quality on Java projects
Implementing Quality on Java projects
 
Combining open source ethics with private interests
Combining open source ethics with private interestsCombining open source ethics with private interests
Combining open source ethics with private interests
 
Evolutions XWiki 2012/2013
Evolutions XWiki 2012/2013Evolutions XWiki 2012/2013
Evolutions XWiki 2012/2013
 
Developing XWiki
Developing XWikiDeveloping XWiki
Developing XWiki
 
XWiki: Developing simple apps quickly
XWiki: Developing simple apps quicklyXWiki: Developing simple apps quickly
XWiki: Developing simple apps quickly
 
XWiki: Building a dynamic Conference web site
XWiki: Building a dynamic Conference web siteXWiki: Building a dynamic Conference web site
XWiki: Building a dynamic Conference web site
 

Recently uploaded

“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
Muhammad Subhan
 
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider  Progress from Awareness to Implementation.pptxTales from a Passkey Provider  Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
FIDO Alliance
 
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
panagenda
 

Recently uploaded (20)

Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...
Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...
Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...
 
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
 
Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024
 
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
 
AI mind or machine power point presentation
AI mind or machine power point presentationAI mind or machine power point presentation
AI mind or machine power point presentation
 
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfThe Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
 
Portal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russePortal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russe
 
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
 
WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024
 
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
 
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsContinuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
 
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdfSimplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
 
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider  Progress from Awareness to Implementation.pptxTales from a Passkey Provider  Progress from Awareness to Implementation.pptx
Tales from a Passkey Provider Progress from Awareness to Implementation.pptx
 
WebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceWebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM Performance
 
State of the Smart Building Startup Landscape 2024!
State of the Smart Building Startup Landscape 2024!State of the Smart Building Startup Landscape 2024!
State of the Smart Building Startup Landscape 2024!
 
TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024TopCryptoSupers 12thReport OrionX May2024
TopCryptoSupers 12thReport OrionX May2024
 
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
 
ADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptxADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptx
 
UiPath manufacturing technology benefits and AI overview
UiPath manufacturing technology benefits and AI overviewUiPath manufacturing technology benefits and AI overview
UiPath manufacturing technology benefits and AI overview
 
Vector Search @ sw2con for slideshare.pptx
Vector Search @ sw2con for slideshare.pptxVector Search @ sw2con for slideshare.pptx
Vector Search @ sw2con for slideshare.pptx
 

Advanced Java Testing

  • 1. Advanced Java Testing What’s next? Vincent Massol, February 2018
  • 2. Agenda •Context & Current status quo •Coverage testing •Testing for backward compatibility •Mutation testing •Environment testing
  • 3. Context: XWiki • Open source wiki • 14 years • 10-15 active committers • Very extensible, scripting in wiki pages • Platform for developing ad-hoc web applications • Strong build practices using Maven and lots of “Quality” plugins • Using Jenkins & custom pipeline library for the CI http://xwiki.org
  • 4. Context: STAMP • Automatic Test Amplification • XWiki SAS participating • Experiment on XWiki project Mutation testing Environment Testing
  • 5. Current Testing Status • 10414 automated tests (in 2.5 hours): • Unit tests (using Mockito) • Integration tests (using Mockito) • Functional (UI) tests (using Selenium/Webdriver)
  • 6. New questions • Are my tests testing enough? Coverage • How can I prevent breaking my users (when I expose some APIs)? Backward compatibility • How good are my tests? Mutation testing • Do my software work in various setups? Environment testing = in place w/ strategy = in progress
  • 7. Test Coverage • Using Jacoco and Clover • Strategy - “Ratchet effect”: • Each Maven module has a threshold • Jacoco Maven plugin fails if new code has less coverage than before in % • Dev is allowed to increase threshold • Global Clover TPC computed automatically once per month on Jenkins for all repos combined Source: http://massol.myxwiki.org/xwiki/bin/view/Blog/ComparingCloverReports 2016-12-20 2017-11-09 +1.9% Harmonized TPC Of course TPC is not panacea. You could have 100% and app not working. Also need functional tests. Aim for 80%.
  • 8. Backward Compatibility • For APIs (and SPIs) • Using the Revapi Maven plugin • Supports source and binary compatibility • Strategy: • Break the build on backward compatibility violations • Add ignores in pom.xml if really needed and ok • Add ignore list in release notes to warn users of your APIs
  • 9. Backward Compatibility • Strategy continued: • Use @Deprecated annotation • Once no more code uses deprecated API, move it to Legacy module.We don’t break backward compatibility! • Use AspectJ in Legacy module to generate and aspectified API (JAR) • Makes code clean and not able to use the Legacy modules (build-enforced) • Distribute the legacy modules public privileged aspect ApiCompatibilityAspect { @Deprecated public boolean Api.checkProgrammingRights() { return this.hasProgrammingRights(); } } Java 8 default methods helped a lot
  • 10. Backward Compatibility • Strategy continued: • For young APIs, use @Unstable + @Since • Enforced by build (to make sure @Since is there). Custom checkstyle rule (or Spoon rule) • Max duration is one cycle (i.e. 1 year). • Enforced by build (fails the build if beyond). /** * ... * @since 9.7RC1 */ @Unstable public List<MacroDescriptor> getMacroDescriptors(Syntax syntax) throws MacroLookupException { ... } Mention that as a result XWiki extensions and scripts can still run in XWiki even several years after they were released.
  • 11. Mutation Testing • Using PIT and Descartes • Concepts • Modify code under test (mutants) and run tests • Good tests kill mutants • Generates a mutation score similar to the coverage % • Descartes = extreme mutations that execute fast and have high values
  • 14. Mutation - Example result =    (getId() == macroId.getId() || (getId() != null && getId().equals(macroId.getId())))    && (getSyntax() == macroId.getSyntax() || (getSyntax() != null && getSyntax().equals(     macroId.getSyntax())));
  • 15. Mutation - Example @Test public void testEquality() {     MacroId id1 = new MacroId("id", Syntax.XWIKI_2_0);     MacroId id2 = new MacroId("id", Syntax.XWIKI_2_0);     MacroId id3 = new MacroId("otherid", Syntax.XWIKI_2_0);     MacroId id4 = new MacroId("id", Syntax.XHTML_1_0);     MacroId id5 = new MacroId("otherid", Syntax.XHTML_1_0);     MacroId id6 = new MacroId("id");     MacroId id7 = new MacroId("id");     Assert.assertEquals(id2, id1);    // Equal objects must have equal hashcode    Assert.assertTrue(id1.hashCode() == id2.hashCode());     Assert.assertFalse(id3 == id1);     Assert.assertFalse(id4 == id1);     Assert.assertFalse(id5 == id3);     Assert.assertFalse(id6 == id1);     Assert.assertEquals(id7, id6);    // Equal objects must have equal hashcode    Assert.assertTrue(id6.hashCode() == id7.hashCode()); } Not testing for inequality! Improved thanks to Descartes!
  • 16. Mutation - Limitations • Takes time to find interesting things to look at and decide if that’s an issue to handle or not. Need better categorisation in report: • Strong pseudo-tested methods:The worst! No matter what the return values are the tests always fail • Pseudo-tested methods: Grey area.The tests pass with at least one modified value. • Multi module support - PITmp • Slow on large projects (e.g. 7+ hours just for xwiki-rendering)
  • 17. Mutation - Strategy • Work in progress, no feedback yet! • Fail the build when the mutation score of a given module is below a defined threshold in the pom.xml • The idea is that new tests should, in average, be of quality equal or better than past tests. • Other idea: hook on CI to run it only on modified code/tests. Ideally: replace coverage check by mutation check(*) (*) But too slow for now to replace coverage, can be done in addition (in a Maven profile for example, or executed on CI).Timeouts are a problem for example.
  • 18. Mutation: Going further • Using DSpot • Uses PIT/Descartes but injects results to generate new tests • Adds assertions to existing tests • Generate new test methods
  • 19. Mutation: Dspot Example public void escapeAttributeValue2() { String escapedText = XMLUtils.escapeAttributeValue("a < a' && a' < a" => a < a" {"); // AssertGenerator add assertion Assert.assertEquals("a &#60; a&#39; &#38;&#38; a&#39; &#60; a&#34; =&#62; a &#60; a&#34; &#123;", escapedText); // AssertGenerator create local variable with return value of invocation boolean o_escapeAttributeValue__3 = escapedText.contains("<"); // AssertGenerator add assertion Assert.assertFalse(o_escapeAttributeValue__3); // AssertGenerator create local variable with return value of invocation boolean o_escapeAttributeValue__4 = escapedText.contains(">"); // AssertGenerator add assertion Assert.assertFalse(o_escapeAttributeValue__4); // AssertGenerator create local variable with return value of invocation boolean o_escapeAttributeValue__5 = escapedText.contains("'"); // AssertGenerator add assertion Assert.assertFalse(o_escapeAttributeValue__5); // AssertGenerator create local variable with return value of invocation boolean o_escapeAttributeValue__6 = escapedText.contains("""); // AssertGenerator create local variable with return value of invocation boolean o_escapeAttributeValue__7 = escapedText.contains("&&"); // AssertGenerator add assertion Assert.assertFalse(o_escapeAttributeValue__7); // AssertGenerator create local variable with return value of invocation boolean o_escapeAttributeValue__8 = escapedText.contains("{"); // AssertGenerator add assertion Assert.assertFalse(o_escapeAttributeValue__8); } Generated test New test @Test public void escapeAttributeValue() { String escapedText = XMLUtils.escapeAttributeValue("a < a' && a' < a" => a < a" {"); assertFalse("Failed to escape <", escapedText.contains("<")); assertFalse("Failed to escape >", escapedText.contains(">")); assertFalse("Failed to escape '", escapedText.contains("'")); assertFalse("Failed to escape "", escapedText.contains(""")); assertFalse("Failed to escape &", escapedText.contains("&&")); assertFalse("Failed to escape {", escapedText.contains("{")); } Original test
  • 20. Mutation: Dspot Strategy • DSpot is very slow to execute. • One strategy is to run it on CI from time to time and in the pipeline commit generated tests in a different source root. • Configure Maven to add a new test directory source using the Maven Build Helper plugin. • Another idea: run it as GitHub commit hook so that it only executed on the modified code.
  • 21. Environment Testing • Environment = combination of Servlet container & version, DB & version, OS, Browser & version, etc • Using Docker • Need: Be able to run functional tests on local dev machines as well as on CI • Lead to using Fabric8 Docker Maven Plugin (DMP)
  • 22. Environment Testing - One maven module to generate the XWiki Docker image for the official distribution - Another maven module to generate the XWiki Maven Docker image (Maven + Browsers installed) - In each functional test module, use the DMP to start the DB Docker image + the XWiki image + the XWiki Maven image. - Execute Maven’s verify goal inside the XWiki Maven image
  • 23. Parting words • Experiment, push the limit! • Some other types of tests not covered and that also need automation • Performance/Stress testing • Usability testing • others?