HEALENIUM -
SELF-HEALING
AUTOMATION
DRILL4J -
TEST TO CODE
MAPPING
DMITRIY GUMENIUK
Senior Delivery Manager,
Product Manager
ReportPortal.io product owner
DelEx Conference organizer
HEALENIUM -
SELF-HEALING TEST
• Problem statement
• How sha works
• Demo
• TAF integration
• POS results
• Future plans
PROBLEMS
Unstable automated E2E tests inhibit CI
~40% team effort spent to fix automations
issues, rather than test product and add new
tests
Web application updates constantly every
sprint, which leads to locator change
PROBLEM STATEMENT
PROBLEMS GOALS FEATURES
Unstable automated E2E tests inhibit CI
~40% team effort spent to fix automations
issues, rather than test product and add new
tests
Web application updates constantly every
sprint, which leads to locator change
Improve E2E automated test stability
Reduce amount of test cases failed due to
non-product issue
Reduces Tests Maintenance efforts
More time to cover new functionality with
tests
Shipping better products faster
PROBLEM STATEMENT
What we
have on the
market
Dynamic
locators
PROS & CONS
• Dynamic DOM state updates
• Easy to write and support tests
• Tests are stable
• Cross-browser, CI, Jira integrations from the box
• Only for new projects
• Strong dependency from tool ecosystem
• May be not secured
• May lose tests when project finished
Healenium
Applicable at any stage of project development
Minimal dependency from the TAF
Replace static locators with dynamic ones
Healenium
Gives ability to find controls (new locator) for updated
WEB pages
Use kinda ML algorithms for Web page changes
identification
Is a standalone Java jar connected to test cases code
base
Helps >2x times reduced test fails because of updated
UI
Provides Html report which handles locators analysis
Provides Intellij Idea plugin to make code updates with
new locator values
HOW HEALENIUM
WORKS
LCS ALGORITHM
Longest common subsequence
problem of finding the longest subsequence common to all sequences in a set of sequences
*widely used by revision control systems such as Git
LCS ALGORITHM MODIFICATION
Longest common subsequence with weight
Added extra weight for tag, Id, class, value, other attributes
<button id=btn-1>
<button id=btn-1>
Healenium selenium (jar)
Tree-comparing(jar)
Includes Tree-comparing dependency
Implements Selenium WebDriver
Overwrites findElement() method
Catch NoSuchElementException
Activates LCS algorithm in Tree-comparing library
Save reference element path to storage
Get reference element path from storage
Get current DOM state
Search in current state for the best subsequence
Generate new CSS locator
JAR LIBRARIES
Self-healing selenium (jar) Tree-comparing(jar)
Reference elements path
storage
Test
Driver.findElement(PageAwareBy(…))
Web Page
Target
element
Find Element
Test Automation Framework
Element Found
Self-healing selenium (jar) Tree-comparing(jar)
Reference elements path
storage
Test
Driver.findElement(PageAwareBy(…))
Web Page
Target
element
Find Element
Test Automation Framework
Element Found
Save successful path
Old locator
Self-healing selenium (jar) Tree-comparing(jar)
Reference elements path
storage
Test
Driver.findElement(PageAwareBy(…))
Web Page
Target
element
Find Element
Element Not Found
Test Automation Framework
Self-healing selenium (jar) Tree-comparing(jar)
Reference elements path
storage
Test
Driver.findElement(PageAwareBy(…))
Web Page
Target
element
Find Element
Element Not Found
Test Automation Framework
Old locator
Successful path
Page state
Self-healing selenium (jar) Tree-comparing(jar)
Reference elements path
storage
Test
Driver.findElement(PageAwareBy(…))
Web Page
Target
element
Find Element
Element Not Found
Test Automation Framework
Old locator New locator
Successful path
Page state
New locator
Self-healing selenium (jar) Tree-comparing(jar)
Reference elements path
storage
Test
Driver.findElement(PageAwareBy(…))
Web Page
Target
element
Find Element
Element Not Found
Test Automation Framework
Old locator New locator
Successful path
Page state
New locator
Find New Element
Self-healing selenium (jar) Tree-comparing(jar)
Reference elements path
storage
Test
Driver.findElement(PageAwareBy(…))
Web Page
Target
element
Find Element
Element Not Found
Test Automation Framework
Element Found
Save successful path
Old locator New locator
Successful path
Page state
New locator
Find New Element
SelfHealingDriver
findElement
public WebElement findElement(By by) {
if (by instanceof PageAwareBy) {
try {
Trying to find the element and save its
path if success
} catch (NoSuchElementException
var5) {
Find previous reference element path in
storage
Generate new best matches locator
return healedLocator;
}
} else {
return delegate.findElement(by);
}
}
PageAwareBy
extends By
PageAwareBy(String pageName, By by,
SelfHealingEngine engine) {
this.pageName = pageName;
this.by = by;
this.engine = engine;
} PageObject Page
Locator
New locator processor
Functions supported
• By() -> PageAwareBy()
• @FindBy -> @PageAwareFindBy
• WebDriver -> SelfHealingDriver
• Iframe support
• Actions support
• Remote test run
• Parallel test run
• Works with Selenium wrappers like Selenide
Html report
Intellij Idea plugin to make code updates
HTML REPORT
Intellij Idea plugin to make code updates
PLUGIN
HTML REPORT
Update
request
{
filename: MainPageWithFindBy
lineNumber: 49
failedLocatorValue://input[@name='EMAIL’]
healedLocatorValue: input.t186__input.js-tilda-rule.t-input
}
Intellij Idea plugin to make code updates
TAF CODE BASE
PLUGIN
HTML REPORT
Find locator and update
Update
request
{
filename: MainPageWithFindBy
lineNumber: 49
failedLocatorValue://input[@name='EMAIL’]
healedLocatorValue: input.t186__input.js-tilda-rule.t-input
}
TAF INTEGRATION
1. Declare custom EngineConfig with the path to store new locators. For example 'shaselenium'
EngineConfig engineConfig = EngineConfig
.custom()
.setStorage(new FileSystemPathStorage(Paths.get("sha", "selenium")))
.build();
2. Init driver instance of SelfHealingDriver
SelfHealingDriver driver = new SelfHealingDriver(new ChromeDriver(), engineConfig);
3. Locate elements
By buttonBy = PageAwareBy.by("MainPage", By.id(testButtonId));
Or
@PageAwareFindBy(page="MainPage", findBy = @FindBy(id = "markup-generation-button"))
WebElement buttonBy;
4. Interact with elements as usual
driver.findElement(buttonBy).click();
Important! Do not delete data from the folder where files with new
locators are stored. They are used to perform self-healing in next
automation runs
Important! "MainPage" is the name of the page to which the
WebElement belongs
RESULTS
100% tests healed
Healed localization testing
Implemented
Idea plugin Mobile support
github.com/healenium
github.com/healenium/healenium-web
github.com/healenium/healenium-appium
Apache2.0 License
DRILL4J -
TEST TO CODE
MAPPING
Coverage?
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
Application under test
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
Modified by commit
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC4
TC5
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1 M2 M3
M4 M5 M6
M7 M8 M9
M10 M11 M12
M13 M14 M15
M16 M17 M18
TC1
TC2
TC3
TC6
M1 M7
M1
5
M1 M7
M1
5
M1 M7
M1
5
M1 M7
You find 95% offails in 5% of time
drill4j.github.io
t.me/drill4j
github.com/Drill4J
Drill4J
with TestToCode plugin

Self healing test automation with Healenium and Minimization of regression suite with Drill4J

  • 1.
  • 2.
    DMITRIY GUMENIUK Senior DeliveryManager, Product Manager ReportPortal.io product owner DelEx Conference organizer
  • 3.
    HEALENIUM - SELF-HEALING TEST •Problem statement • How sha works • Demo • TAF integration • POS results • Future plans
  • 4.
    PROBLEMS Unstable automated E2Etests inhibit CI ~40% team effort spent to fix automations issues, rather than test product and add new tests Web application updates constantly every sprint, which leads to locator change PROBLEM STATEMENT
  • 5.
    PROBLEMS GOALS FEATURES Unstableautomated E2E tests inhibit CI ~40% team effort spent to fix automations issues, rather than test product and add new tests Web application updates constantly every sprint, which leads to locator change Improve E2E automated test stability Reduce amount of test cases failed due to non-product issue Reduces Tests Maintenance efforts More time to cover new functionality with tests Shipping better products faster PROBLEM STATEMENT
  • 6.
    What we have onthe market
  • 7.
  • 8.
    PROS & CONS •Dynamic DOM state updates • Easy to write and support tests • Tests are stable • Cross-browser, CI, Jira integrations from the box • Only for new projects • Strong dependency from tool ecosystem • May be not secured • May lose tests when project finished
  • 9.
    Healenium Applicable at anystage of project development Minimal dependency from the TAF Replace static locators with dynamic ones
  • 10.
    Healenium Gives ability tofind controls (new locator) for updated WEB pages Use kinda ML algorithms for Web page changes identification Is a standalone Java jar connected to test cases code base Helps >2x times reduced test fails because of updated UI Provides Html report which handles locators analysis Provides Intellij Idea plugin to make code updates with new locator values
  • 11.
  • 12.
    LCS ALGORITHM Longest commonsubsequence problem of finding the longest subsequence common to all sequences in a set of sequences *widely used by revision control systems such as Git
  • 13.
    LCS ALGORITHM MODIFICATION Longestcommon subsequence with weight Added extra weight for tag, Id, class, value, other attributes <button id=btn-1> <button id=btn-1>
  • 14.
    Healenium selenium (jar) Tree-comparing(jar) IncludesTree-comparing dependency Implements Selenium WebDriver Overwrites findElement() method Catch NoSuchElementException Activates LCS algorithm in Tree-comparing library Save reference element path to storage Get reference element path from storage Get current DOM state Search in current state for the best subsequence Generate new CSS locator JAR LIBRARIES
  • 15.
    Self-healing selenium (jar)Tree-comparing(jar) Reference elements path storage Test Driver.findElement(PageAwareBy(…)) Web Page Target element Find Element Test Automation Framework Element Found
  • 16.
    Self-healing selenium (jar)Tree-comparing(jar) Reference elements path storage Test Driver.findElement(PageAwareBy(…)) Web Page Target element Find Element Test Automation Framework Element Found Save successful path Old locator
  • 17.
    Self-healing selenium (jar)Tree-comparing(jar) Reference elements path storage Test Driver.findElement(PageAwareBy(…)) Web Page Target element Find Element Element Not Found Test Automation Framework
  • 18.
    Self-healing selenium (jar)Tree-comparing(jar) Reference elements path storage Test Driver.findElement(PageAwareBy(…)) Web Page Target element Find Element Element Not Found Test Automation Framework Old locator Successful path Page state
  • 19.
    Self-healing selenium (jar)Tree-comparing(jar) Reference elements path storage Test Driver.findElement(PageAwareBy(…)) Web Page Target element Find Element Element Not Found Test Automation Framework Old locator New locator Successful path Page state New locator
  • 20.
    Self-healing selenium (jar)Tree-comparing(jar) Reference elements path storage Test Driver.findElement(PageAwareBy(…)) Web Page Target element Find Element Element Not Found Test Automation Framework Old locator New locator Successful path Page state New locator Find New Element
  • 21.
    Self-healing selenium (jar)Tree-comparing(jar) Reference elements path storage Test Driver.findElement(PageAwareBy(…)) Web Page Target element Find Element Element Not Found Test Automation Framework Element Found Save successful path Old locator New locator Successful path Page state New locator Find New Element
  • 23.
    SelfHealingDriver findElement public WebElement findElement(Byby) { if (by instanceof PageAwareBy) { try { Trying to find the element and save its path if success } catch (NoSuchElementException var5) { Find previous reference element path in storage Generate new best matches locator return healedLocator; } } else { return delegate.findElement(by); } }
  • 24.
    PageAwareBy extends By PageAwareBy(String pageName,By by, SelfHealingEngine engine) { this.pageName = pageName; this.by = by; this.engine = engine; } PageObject Page Locator New locator processor
  • 25.
    Functions supported • By()-> PageAwareBy() • @FindBy -> @PageAwareFindBy • WebDriver -> SelfHealingDriver • Iframe support • Actions support • Remote test run • Parallel test run • Works with Selenium wrappers like Selenide
  • 26.
  • 27.
    Intellij Idea pluginto make code updates HTML REPORT
  • 28.
    Intellij Idea pluginto make code updates PLUGIN HTML REPORT Update request { filename: MainPageWithFindBy lineNumber: 49 failedLocatorValue://input[@name='EMAIL’] healedLocatorValue: input.t186__input.js-tilda-rule.t-input }
  • 29.
    Intellij Idea pluginto make code updates TAF CODE BASE PLUGIN HTML REPORT Find locator and update Update request { filename: MainPageWithFindBy lineNumber: 49 failedLocatorValue://input[@name='EMAIL’] healedLocatorValue: input.t186__input.js-tilda-rule.t-input }
  • 30.
  • 31.
    1. Declare customEngineConfig with the path to store new locators. For example 'shaselenium' EngineConfig engineConfig = EngineConfig .custom() .setStorage(new FileSystemPathStorage(Paths.get("sha", "selenium"))) .build(); 2. Init driver instance of SelfHealingDriver SelfHealingDriver driver = new SelfHealingDriver(new ChromeDriver(), engineConfig); 3. Locate elements By buttonBy = PageAwareBy.by("MainPage", By.id(testButtonId)); Or @PageAwareFindBy(page="MainPage", findBy = @FindBy(id = "markup-generation-button")) WebElement buttonBy; 4. Interact with elements as usual driver.findElement(buttonBy).click(); Important! Do not delete data from the folder where files with new locators are stored. They are used to perform self-healing in next automation runs Important! "MainPage" is the name of the page to which the WebElement belongs
  • 32.
  • 33.
    100% tests healed Healedlocalization testing
  • 34.
  • 35.
  • 36.
    DRILL4J - TEST TOCODE MAPPING
  • 37.
  • 38.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 Application under test
  • 39.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18
  • 40.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6
  • 41.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6
  • 42.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1
  • 43.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7
  • 44.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5
  • 45.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1
  • 46.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7
  • 47.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7 M1 5
  • 48.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5
  • 49.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5
  • 50.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5
  • 51.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7
  • 52.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7
  • 53.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 M2 M3 M4 M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18
  • 54.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 M2 M3 M4 M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 Modified by commit
  • 55.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 M2 M3 M4 M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7
  • 56.
    M1 M2 M3 M4M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC4 TC5 TC6 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 M2 M3 M4 M5 M6 M7 M8 M9 M10 M11 M12 M13 M14 M15 M16 M17 M18 TC1 TC2 TC3 TC6 M1 M7 M1 5 M1 M7 M1 5 M1 M7 M1 5 M1 M7
  • 62.
    You find 95%offails in 5% of time
  • 64.