My Profile Photo

Paul Brodner's Blog

Opinions are my own and not the views of my employer


Tips & Tricks


    Neo4J analysis on Test Results

    Use Case

    Test results executed in a Jenkins job or from local machine can be stored and analised using a graph based database as Neo4j. Why: because is much easier and intuitive to represent data usign graphs.

    Neo4j is a Graph Database wich help us to visualize and analyze data using its own query language called Cypher

    Start Neo4J

    I am using here docker-compose to spin up easily a desired version.

    As you can see bellow, I’m adding volume shares from host to guest container.

    • in data I save the Jenkins results (xml) - that ca be parsed and normilized to be sent to Neo4J
    • in logs - I save DB logs
    # docker-compose.yml
    version: '2'
    services:    
      neo4j:  
        image: neo4j:3.5
        volumes: 
          - ./data:/data
          - ./data/logs:/logs
        ports:
          - 7474:7474
          - 7687:7687
        environment:
          - NEO4J_AUTH=neo4j/admin
          - NEO4JLABS_PLUGINS='["graph-data-science"]'
    

    Graph Database for Test Case Analysis

    this is the graph database “schema” that we can use to analyze the Test Case executed on a particular build

    neo4j

    Cypher Queries

    read more here about Cypher

    // cleanup
    MATCH (n) DETACH DELETE n
    
    // how many tags not related to B- 
    MATCH (t:Tag) where not(t.name contains "B-")  RETURN t.name
    
    • duration
    //what are the top 20 slowest test suites 
    MATCH (p:Project)-[]->(b:Build)-[e]->(ts:TestSuite) WHERE p.name="projecA-238"  RETURN distinct(ts.name), b.name, e.duration/60 as durationInMinutes ORDER BY durationInMinutes DESC LIMIT 20
    
    // what are the top 20 slowest tests
    MATCH (p:Project)-[]->(b:Build)-[e]->(ts:TestSuite)-[r]->(tc:TestCase) WHERE p.name="projecA-238"  RETURN distinct(tc.name), b.name, r.duration/60 as durationInMinutes ORDER BY durationInMinutes DESC LIMIT 20
    
    // How much time do we spent on teardown
    MATCH (teardown:Teardown)-[clean]->(testSuite:TestSuite)<-[]-(build:Build)<-[]-(project:Project) WHERE project.name='projecA-238' MATCH (teardown)-[]->(library:Library) RETURN distinct(teardown.name) as teardownName, count(*) as usage , sum(clean.duration/60) as durationMin, library.name ORDER BY usage DESC
    
    // How much time do we spent on precondition
    MATCH (setup:Setup)-[sr]->(testSuite:TestSuite)<-[]-(build:Build)<-[]-(project:Project) WHERE project.name='projecA-238' RETURN distinct(setup.name), count(setup) as usage, sum(sr.duration) ORDER BY usage DESC
    
    MATCH (setup:Setup)-[sr]->(testSuite:TestSuite)<-[]-(build:Build)<-[]-(project:Project) WHERE project.name='projecA-238' MATCH (setup)-[]->(library:Library) RETURN distinct(setup.name), count(setup) as usage, sum(sr.duration/60) as durationMin, library.name ORDER BY usage DESC
    
    • Pass/Fail
    //how many setup conditions failed per stories
    MATCH (project:Project)-[]->(b:Build)-[r]->(ts:TestSuite)<-[s:PREPARE]-(setup:Setup) WHERE project.name="projecA-238" and s.status="FAIL" MATCH (ts)-[]->(t:TestCase) return ts.name, setup.name, s.duration/60 as setupDuration, s.status, count(t) as FailedTestCase order by FailedTestCase DESC
    
    // test cases failed per suite
    MATCH (testSuite:TestSuite)-[ex]->(testCase:TestCase) where ex.status="FAIL" return testSuite.name, count(testCase) as testCaseFailed  order by testCaseFailed DESC
    
    • count
    //how many calls are made to a particular test step
    
    MATCH (n:TestStep)<-[s:STEP_OF]-(f) return distinct(n.name), count(s) as uni order by uni desc limit 20