/
System Architecture

System Architecture

System Overview


The Safety Analysis system consists of three main parts: Safety Analysis - Sonar,  Safety Analysis - GUI/CLI and Safety Analysis - WebApp. All of them are made of several modules rendered in the source code as maven modules.

The Safety Analysis - GUI/CLI is a desktop application.

The Safety Analysis - WebApp is a web application (war) and as such must be deployed into an application container, the Apache Tomcat is recommended. It also need a database connection. MySQL is recomended.

The Safety Analysis - Sonar is a plugin to analyse source code of whole system.

Events Tree

Description

Events Tree allow to create diagrams which an event (scenario) is analyzed using Boolean logic to examine a chronological series of subsequent consequences of initial event, including the calculation of the probability of the scenario and his consequences. 

Events Tree Documentation

Events Tree XML Specification

Below you can see all variables that are used to describe event tree in XML.

EventTree Field

   id - identifier of Event Tree

   InitialBranch - contains all the information needed to create a tree

InitialBranch Field

   type - did the event happen or not (values "true" or "false")

   child - optional section, occurs only when the branch has a child (InitialBranch always has children), has identical structure as InitialBranch

   event - event description section, detailed description later in this document

   id - edge identifier

InitialBranch field have the same structure as any other edge.


Fig 1. EventTree from InitialBranch

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <eventTree xmlns:ns2="pl.wroc.pw.sa.et.EventTree">
	<id>1</id>
	<InitialBranch>
    		<branch>true</branch>
    		<child>
          	    ...
       		</child>
        	<child>
		    ...
		</child>
        	<event>
		    ...
        	</event>
		<id>7</id>
    		<type>true</type>
	</InitialBranch>
</eventTree> 

Event 

Event stores informations about him on each branch.

Event Field

   event id

   name

   child - our event child, saved in the same way as his parent.

Trapezoid Field

   name

   parameters

Parameters

   scale (LINEAR or LOGARITHMIC)

   type 

   fuzzy function parameters: abc and d

   length

   probability

Fig.2 Event without child

 <event>
 	<trapezoid>
    	<name>nn</name>
        	<parameters>
            	<scale>LINEAR</scale>
                	<a>0.5</a>
                    <b>0.5</b>
                    <c>0.5</c>
                    <d>0.5</d>
                <length>0.0</length>
             <prob>0.0</prob>
         </parameters>
      </trapezoid>
	  <id>5</id>
      <name>e6</name>
 </event>


Fig.3 Event with child

 <event>
 	<trapezoid>
 		<name>nn</name>
 			<parameters>
 				<scale>LINEAR</scale>
                <a>0.5</a>
                <b>0.5</b>
                <c>0.5</c>
                <d>0.5</d>
                <length>0.0</length>
                <prob>0.0</prob>
            </parameters>
     </trapezoid>
         	<child>
                <trapezoid>
                    <name>nn</name>
                    	<parameters>
                        	<scale>LINEAR</scale>
                        	<a>0.5</a>
                        	<b>0.5</b>
                        	<c>0.5</c>
                        	<d>0.5</d>
                            <length>0.0</length>
                            <prob>0.0</prob>
                    	</parameters>
                	</trapezoid>
                	<id>5</id>
                	<name>e6</name>
            	</child>
            <id>4</id>
		<name>e5</name>
  </event>

Acceptance tests specification

Fault Tree

Description

This module allows to create a fault tree diagram. Fault tree is a top-down, deductive method of analyzing in which undesired state of a system is represented and analyzed using Boolean logic to combine a series of low-level events.

Fault Tree XML Specification

Variables used to describe Fault Tree in XML

FaultTree Fields

   root - event tree identity

   faultMap - map of failures, contains at least one entry section

   scale - (LINEAR or LOGARITHMIC)

Root fields

   name

   triangleFunction→name - function name

Fig 1. Fault Tree

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<faultTree>
    <root>
        <name>root</name>
        <triangleFunction>
            <name></name>
        </triangleFunction>
    </root>
    <faultMap>
           <entry>
             ...
           </entry>
           <entry>
             ...
           </entry>
    </faultMap>
    <scale/>
</faultTree>

Entry

Entry and Entry → Value fields

   key - entry key

   value - entry value

   value→name - value name

   value→triangleFunction→name - function name

Parent fields

   name

   logicGateType - GATE_AND or GATE_OR

   triangleFunction→name - function name

Fig.2 Entry

<entry>
	<key>fault2</key>
	<value>
		<name>fault2</name>
		<parent>
			<logicGateType>GATE_AND</logicGateType>
			<parent>
                <name>fault1</name>
                <parent>
                    logicGateType>GATE_OR</logicGateType>
                    <parent>
                    	<name>root</name>
                        <triangleFunction>
                        	<name></name>
                        </triangleFunction>
                    </parent>
                </parent>
                <triangleFunction>
                   	<name></name>
            	</triangleFunction>
            </parent>
        </parent>
        <triangleFunction>
           	<name>dużo3</name>
    	</triangleFunction>
	</value>
</entry>

Fuzzy Reasoning

Description

Class supporting operation on fuzzy sets with trapezoid and triangle shapes. Supported sets of first and second type.

Fuzzy reasoning XML Specification

Fuzzy set main parameters:

   scale LINEAR or LOGARITHMIC

   type - set type (FIRST or SECOND)

   length - distance between the points that characterize the lower and upper membership functions

   prob lower limit for fuzzy set

Trapezoid

   a, b, c and - trapezoid parameters

Fig 1. Trapezoid parameters

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<paramTrapezoid>
    <scale>LINEAR</scale>
    <type>SECOND</type>
    <a>0.1</a>
    <b>0.2</b>
    <c>0.3</c>
    <d>0.4</d>
    <length>0.04</length>
    <prob>0.05</prob>
</paramTrapezoid>

Triangle

   a, b and c -  triangle parameters

Class diagram

Web App

The web application is written using Spring Boot. The web app module consists of:

  1. Main app class (SafetyWebApplication)
    This application is basically the class that contains main method. It is used to run the application. The class is annotated with @SpringBootApplication annotation, which tells Spring that it is spring boot application. Spring does the basic configuration for our app, so we don't have to write web.xml, persistenceContext.xml or any other configuration files. The class also configures Swagger, which generates the Rest Api Documentation (after program starts it is available here: localhost:8080/swagger-ui.html).
  2. Controllers:
    2.1 Rest Controllers (annotated with @RestController). They are used to perform some actions (for example adding a false tree).
    2.2 MVC Controllers (annotated with @Controller). They are used to return some view, that is more user-friendly than plain text.
    Here you can read more about the differences between rest controllers and mvc controllers: https://www.genuitec.com/spring-frameworkrestcontroller-vs-controller/
  3. Services:
    Methods from services are called from controllers. For example if controller wants to add new fault tree to the database, it only calls the appropriate method form service and the core logic is placed in services. We don't put any logic in controllers. Services are the layer between controller and repository.
  4. Resources
    Here are HTML files for our views (in folder templates) and application.properties file. We use thymeleaf as a view template. Here is the documentation:

    http://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

    http://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html

Database connection

To connect to database you need to run the application and go to this link: localhost:8080/h2-console. There you have to put properties from application.properties there:

It has to look like that:

Full JDBC URL: jdbc:h2:./test;DB_CLOSE_DELAY=- 1;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE

User name: user

Password: pass

Swagger Documentation

The REST API documentation is available here: localhost:8080/swagger-ui.html
It looks like that:

If you want to see, what request parameters you have to send or what is response for some request, just click on the path that is point of your interest and read everything. Here is an example:

Dependencies

The web app module uses following dependencies:

  • spring-boot-starter-data-jpa - includes Hibernate,
  • spring-boot-starter-thymeleaf - thymeleaf is a template engine for creating views on the server site,
  • spring-boot-starter-web - includes Spring MVC, the core dependency of this module,
  • spring-boot-devtools - nice developer tools, that helps to work more efficiently. Here you can read more: 
    https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html
  • h2 - includes h2 database,
  • spring-boot-starter-test - includes most popular testing frameworks (for example JUnit, Mockito, AssertJ),
  • springfox-swagger2 - includes swagger, that generates documentation,
  • springfox-swagger-ui - generates swagger gui,
  • safety-model
  • safety-eventstree
  • safety-faulttree
  • safety-api
  • safety-report

For versions of this dependencies, go to pom.xml in safety-web module.


Creating Reports

ReportGenerator

Class for generating raports of course of action of application Safety Analysis. Document has fixed paragraphs for date, logo and title. Order of other paragraphs depends on what parameters program Safety Analysis has been launched with.

Class includes several features which modify created report. Class ReportGenerator is used to integrate features of another classes which together create object of a report.

Instance for content of report is a class TextDocument which can be modified by adding additional chunks of data to an object. That chunk is another class called Paragraph which instantiates TextDocument's data.

Raw text document consists of object of TextDocument. TextDocument consists of objects of Paragraph. Paragraph consists data which report presents.

By default report can be generated as empty text document which is created with constructor with no arguments given. There's second constructor which creates text document with prebuilt three paragraphs consisting date, logo and title.


Code formatting

The source code should be formatted according to default settings of the last version of IntelliJ IDEA.

Naming convention

  • Classes

    We are using UpperCamelCase. We want to describe as good as possible what class defines. We are using nouns to show what class defines.

  • Methods


    We are using camelCase. We want to describe as good as possible what does the method do. We are using verbs to show what does the method do. In case of boolean methods we are using names such as "isApplicationValid()". 
  • Variables

    We are using camelCase. We want to describe as good as possible what variable represents. We are using verbs epithets to show variable represents. In case of boolean variable we are using names such as "isCorrect". 

Development environment

Before you start develop Safety Analysis you have to prepare your environment to work. 

Here is a list with tools you need to download and install

  • Latest Java 8 JDK
  • Latest Java 8 JRE
  • Apache Tomcat 9.0 or later
  • IntelliJ
  • Maven 3.3 or later

After installation please check-out your branch from our repository and connect to the repository in IntelliJ.

Testing

To ensure reliability and stability of Safety Analysis a variety of tests are performed. We are using JUnit, Pi-test and other Java extensons connected with tests. Actually we started to introduce Cucumber as a new tool for acceptance tests.

During execution of all tests bugs and issues are found. Analysis of tests results is available here.

Acceptance tests

Software testing method conducted to determine if the requirements of a specification or contract are met. It may involve User Acceptance Testing (UAT), Operational Acceptance Testing (OAT), Acceptance testing in extreme programming, alpha and beta testing. You write acceptance tests to check if your code is passing the requirements of project. You should run these tests in integration-test phase. Naming param is *prefix*AT.java.

Component tests

Component testing is a method where testing of each component in an application is done separately. Suppose, in an application there are 5 components. Testing of each 5 components separately and efficiently is called as component testing. It finds the defects in the module and verifies the functioning of software. Component tests use spring context or in memory database. Naming param is *className*IT.java.

Unit tests

Software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use.Unit testing is commonly automated, but may still be performed manually. The objective in unit testing is to isolate a unit and validate its correctness. You should write JUnit to check every function that you use in your code. JUnit must be fast, it should be matters of seconds to run that test. JUnit should test only define unit of system. Naming param is *className*Test.java.

Command Line Use Case Tests Specification

This page contains documentation for CLI Use Case Tests in order of appearance in code.

TestParser test - unrecognized argument
DescriptionThis test checks GNU Parser for use of unrecognized argument.
ConditionsArgument must be one of given in tables above.
Test procedure
      1. Pass the argument to CLI "-l"
      2. Compare result with expected result
Expected resultsOutput string: "Encountered exception while parsing using GnuParser:\nUnrecognized option: -l"

TestAnalyze Fault Tree - no tree loaded
DescriptionThis test checks correctness of Fault Tree Analysis.
ConditionsNo tree loaded.
Test procedure
      1. Pass the argument to CLI "-a"
      2. Call the method
      3. Compare result with expected result
Expected resultsOutput string: "There is no tree that I could analyze."

TestCheck the Cohesion of Event Tree - no tree loaded
DescriptionThis test checks cohesion of Event Tree.
ConditionsNo tree loaded.
Test procedure
      1. Pass the argument to CLI "-c"
      2. Call the method
      3. Compare result with expected result
Expected resultsOutput string: "There is no tree that I could analyze."

TestGet Fuzzy Importance Index of Fault Tree - no tree loaded
DescriptionThis test gets fuzzy importance index of fault tree.
ConditionsNo tree loaded.
Test procedure
      1. Pass the argument to CLI "-i"
      2. Call the method
      3. Compare result with expected result
Expected resultsOutput string: "There is no tree that I could analyze."


TestLoad Event Tree - wrong tree
DescriptionThis test checks Event Tree loading from file.
Conditions-
Test procedure
      1. Pass the argument to CLI "-e wrong.xml"
      2. Call the method
      3. Compare result with expected result
Expected resultsOutput string: "\nRead Event Tree file from: wrong.xml Fail"

TestLoad Fault Tree - wrong tree
DescriptionThis test checks Fault Tree loading from file.
Conditions-
Test procedure
      1. Pass the argument to CLI "-f wrong.xml"
      2. Call the method
      3. Compare result with expected result
Expected resultsOutput string: "\nRead Fault Tree file from: wrong.xml Fail"

TestLoad Event Tree - correct tree
DescriptionThis test checks Event Tree loading from file.
Conditions-
Test procedure
      1. Pass the argument to CLI "-e treeXmltest2.xml"
      2. Call the method
      3. Compare result with expected result
Expected resultsOutput string: "\nRead Event Tree file from: treeXmltest2.xml Success"

TestCheck Cohesion of Event Tree
DescriptionThis test checks cohesion of Event Tree.
ConditionsSucesfully load Event Tree from file.
Test procedure
      1. Pass the argument to CLI "-e treeXmltest2.xml -c"
      2. Call the method
      3. Compare result with expected result
Expected resultsOutput string: "\nRead Event Tree file from: treeXmltest2.xml Success\n"Result of the analysis Events Tree: \nEvents tree is ok"

TestCheck Report generation
DescriptionThis test checks report generation.
Conditions-
Test procedure
      1. Pass the argument to CLI "-r Report.odt"
      2. Call the method
      3. Compare result with expected result
Expected resultsOutput string: "\nCreated file: Report.odt"

TestLoad Fault Tree - correct tree
DescriptionThis test checks Fault Tree loading from file.
Conditions-
Test procedure
      1. Pass the argument to CLI "-f exampleFaultTree.xml"
      2. Call the method
      3. Compare result with expected result
Expected resultsOutput string: "\nRead Fault Tree file from: exampleFaultTree.xml Success"

TestGet Fuzzy Importance Index of Fault Tree
DescriptionThis test gets fuzzy importance index of fault tree.
ConditionsSucesfully loaded Fault Tree.
Test procedure
      1. Pass the argument to CLI "-f exampleFaultTree.xml -i"
      2. Call the method
      3. Compare result with expected result
Expected resultsOutput string: "\nRead Fault Tree file from: exampleFaultTree.xml Success\nResult of the analysis Fault Tree: \nKey: root = Value: "


Cucumber

Cucumber is a tool that we use for write acceptable tests. It runs automated acceptance tests written in a behaviour-driven development (BDD) style. Cucumber defines application behaviour using simple English text, defined by a language called Gherkin, which make tests easy to read and understand for people that don't have much experience with programming. Another advantage of this tests environment is, that it automatically generates report for the conducted test, which might help with analysing tests results.

More informations about Cucumber are available in documentation.

Testing with cucumber

Note: Our project is already prepared to work with Cucumber, so you don't have to re-configure your environment.

To make a executable test you have to prepare Feature,Steps Definition and Runner files.

In our project Feature file should be located in safetyanalysis/moduleName/src/test/resources/cucumber/FileName.feature, Step Definition file in safetyanalysis/moduleName/src/test/java/steps/FileNameSteps.java and Runner file in safetyanalysis/moduleName/src/test/java/FileName.java

Feature files

Feature file includes test scenario description written in Gherkin language. Using basic English language we can describe every single step of our test. It includes feature which is tested, concrete scenarios for this features and test steps.

Example of feature file (source):

Example code for feature
Feature: Withdraw Money from ATM

    A user with an account at a bank would like to withdraw money from an ATM.
    Provided he has a valid account and debit or credit card, he should be allowed to make the transaction. The ATM will tend the requested amount of money, return his card, and subtract amount of the withdrawal from the user's account.

    Scenario: First scenario title
        Given preconditions
        When actions
        Then results

    Scenario: Second scenario title
        ...

A feature file consists of 2 main parts:

  • Feature - Feature contains detailed description of tested feature and test reason. This part is not required, but it makes our test more understandable and helps to analyse test result.
  • Scenario - Each scenario consist of steps, which have to be passed to finish test with success.

Every step has to start in new line with one of the keywords:

    • Given - It describes the pre-requisite for the test to be executed. Example - GIVEN I am a Facebook user.

    • When - It defines the trigger point for any test scenario execution. Example − WHEN I enter "<username>".

    • Then - It holds the expected result for the test to be executed. Example − THEN login should be successful.

    • And - It provides the logical AND condition between any two statements. AND can be used in conjunction with GIVEN, WHEN and THEN statement. Example − WHEN I enter my "<username>" AND I enter my "<password>".

    • But - It signifies logical OR condition between any two statements. OR can be used in conjunction with GIVEN, WHEN and THEN statement. Example − THEN login should be successful. BUT home page should not be missing.

Using those keywords you can create any test you want.

Step definitions file

It is a file which contains steps definitions. Without him, steps defined in Feature file are just simple words. It contains source code which should be done within a test step. Parameters defined in feature files are passed to step definitions with regular expressions. To make them work correctly, you should configure methods for each step defined in Feature file. Each step is preceded by an annotation connected to step keywords defined in feature file (e.g. @Then )


Here's example code for step descriptions (first part is Feature code, second is step definitions) (source): 

Example - Part of Feature file
/*------------------------------- Feature file ----------------------------*/
Feature: F1
	Scenario: S1
		Given first value 2
		Given second value 3
		When first value is 2
		And second value is 3
		Then multiplication result is 6
Example - Part of Step definition file
/*-------------------------- Step definitions file ------------------------*/
/*packages and imports*/

public class MathMull {

    @Before
    public void beforeScenario() {
        math = new MathMull;
    }

    @After
    public void afterScenario() {
    }

    @Given("^first value (-?\\d)$")
    public void setFirstValue(int var) throws Throwable {
        var1 = var;
    }

    @Given("^second value (-?\\d)$")
    public void setSecondValue(int var) throws Throwable {
        var2 = var;

    @When("^first value is (-?\\d)$")
    public void compareFirst(int var) throws Throwable {
        var1 == var;


    @And("^second value is (-?\\d)$")
    public void compareSecond(int var) throws Throwable {
        var2 == var;


	@Then("^multiplication result is (-?\\d)$")
	public void compareMultiplication(int var) throws Throwable {
    	var1*var2 == var;
	}
}

In this example you can see, how every steps from Feature file (upper part) have to be written in Step definition file (lower part). Even if you make the same method, but written with different words you will have to add another definition to step definition file. This is very important, because every missed step definition make that your test does not be complete, and in consequence it will not end with success.

Another thing is, that in Step definition file, there are two steps that are not in Feature file, @Before and @After. Both are used to do things before and after tests. It might be helpful, if we have for example to create class which is require to tests.

You can see below more concrete example: 

Example code for Step description
/*here are packages and imports*/

public class EventTreeAcceptanceTestSteps {

    private EventTree tree;
    private BufferedReader br;
    private String filepath;
    private EventTree newTree;

    @Before
    public void beforeScenario() {
        tree = new EventTree();
    }

    @After
    public void afterScenario() {
    }

    @Given("^I have an event tree$")
    public void iHaveAnEventTree() throws Throwable {
        assertNotNull(tree);
    }

    @When("^I set its ID to (-?\\d)$")
    public void iSetItsIDTo(int ID) throws Throwable {
        tree.setId(ID);


	@Then("^The event tree should be defined with string \"([^\"]*)\"$")
	public void theEventTreeShouldBeDefinedWithString(String eventTreeString) throws Throwable {
    	assertEquals(eventTreeString, tree.toString());
	}

	@When("^I add an init event$")
	public void iAddAnInitEvent() throws Throwable {
   	Event e1 = new Event();
    	tree.addInitEvent(e1);
	}
(...)
}

Runner file

In Runner file you have to set all options about tests, like which features are tested or where steps are located. There's few more options to configure but they are optional, the main thing of this file is that he making our test code working.

Required options are:

  • format - It describes how cucumber will format test case output and if it create reports.
  • glue - It contains path to package containing Step definition files
  • features - It contains path to feature file.


Example code for running tests:

Example code for Run
package pl.wroc.pwr.sa.et;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(
        format = { "pretty", "html:target/cucumber" },
        glue = "pl.wroc.pwr.sa.et.steps",
        features = "classpath:cucumber/EventTree.feature"
)
public class EventTreeAcceptanceTest {
}

 
To run our test all we have to do is just run our test
 

If everything was configured correct, we should got message about completed tests.

After completed tests Cucumber automatically generate report file, where you can check what was tested, or if something went wrong where was the problem. Report file is generated as file safetyanalysis/moduleName/target/cucumber/index.html.

Scenario outline - alternative scenario type

In some situations, when we want to test for example results of some mathematic function making the same scenario with different values doesn't make sense. Alternatively you can use Scenario outline in place of normal Scenario to test multiple values at the same scenario. All what you have to do is write tests where instead static values you have to write <variableName>. Later, after describing scenario all you have to do is make after Examples: keyword table, with values for each variant of this scenario. Here you have example of code which use this feature (source):

Example code for feature
Feature: (...)


Scenario Outline: A user withdraws money from an ATM
    Given <Name> has a valid Credit or Debit card
    And their account balance is <OriginalBalance>
    When they insert their card
    And withdraw <WithdrawalAmount>
    Then the ATM should return <WithdrawalAmount>
    And their account balance is <NewBalance>

    Examples:
      | Name   | OriginalBalance | WithdrawalAmount | NewBalance |
      | Eric   | 100             | 45               | 55         |
      | Pranav | 100             | 40               | 60         |
      | Ed     | 1000            | 200              | 800        |


Example test

Here you can see example test of events tree class. Below is code for all three files, which allow to run correctly this test.

Feature file

File located in safetyanalysis/safety-eventstree/src/test/resources/cucumber/EventTree.feature

Example - Feature
Feature: EventTree
  As a user
  I want to create an event tree with three events and save it to xml file
  So that I don't need to create it once again
  Scenario: Create an Event Tree, set its description, add three events and save it to XML file
    Given I have an event tree
    When I set its description to "Drzewo zdarzen"
    And I set its ID to 5
    And I add an init event
    And I add a second event to tree
    And I add a third event to tree
    Then The event tree should be defined with string "(5,3,7|0:0|1:1,2|2:3,4,5,6)"
    And Its description should be "Drzewo zdarzen"
    When I save my event tree to XML file called "eventTree.xml"
    Then XML file should be available
    When I load stored xml file
    Then File should not be empty
    And XML file should contain my event tree
    When I load an event tree from stored xml file
    Then A new event tree should be created
    And New events tree description should be "Drzewo zdarzen"
    And New event tree should be defined with string "(5,3,7|0:0|1:1,2|2:3,4,5,6)"
    But New event tree should not be defined with string "(5,2,3|0:0|1:1,2)"
    


Step Definition file

File located in safetyanalysis/safety-eventstree/src/test/java/steps/EventTreeATSteps.java

Example - Steps definition
package pl.wroc.pwr.sa.et.steps;

import cucumber.api.java.Before;
import cucumber.api.java.en.*;
import pl.wroc.pwr.sa.et.Event;
import pl.wroc.pwr.sa.et.EventTree;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import static org.junit.Assert.*;

/**
 * Created by Patryk on 11.05.2017.
 */
public class EventTreeATSteps {

    private EventTree tree;
    private BufferedReader bufferedReader;
    private String filepath;
    private EventTree newTree;

    @Before
    public void beforeScenario() {
        tree = new EventTree();
    }

    @Given("^I have an event tree$")
    public void iHaveAnEventTree() throws Exception {
        assertNotNull(tree);
    }

    @When("^I set its ID to (-?\\d)$")
    public void iSetItsIDTo(int ID) throws Exception {
        tree.setId(ID);
    }

    @Then("^The event tree should be defined with string \"([^\"]*)\"$")
    public void theEventTreeShouldBeDefinedWithString(String eventTreeString) throws Exception {
        assertEquals(eventTreeString, tree.toString());
    }

    @And("^I add an init event$")
    public void iAddAnInitEvent() throws Exception {
        tree.addInitEvent(new Event());
    }

    @And("^I set its description to \"([^\"]*)\"$")
    public void iSetItsDescriptionTo(String description) throws Exception {
        tree.setDescription(description);
    }

    @And("^Its description should be \"([^\"]*)\"$")
    public void itsDescriptionShouldBe(String description) throws Exception {
        assertEquals(description, tree.getDescription());
    }

    @And("^I add a second event to tree$")
    public void iAddASecondEventToTree() throws Exception {
        tree.addEvent(new Event());
    }

    @And("^I add a third event to tree$")
    public void iAddAThirdEventToTree() throws Exception {
        tree.addEvent(new Event());
    }

    @When ("^I save my event tree to XML file called \"([^\"]*)\"$")
    public void iSaveMyEventTreeToXMLFileCalled(String filename) throws Exception {
        EventTree.saveTreeToXML(filename, tree);
        filepath = filename;
    }

    @Then("^A new event tree should be created$")
    public void aNewEventTreeShouldBeCreated() throws Exception {
        assertNotNull(newTree);
    }

    @Then("^XML file should be available$")
    public void xmlFileShouldBeAvailable() throws Exception {
        assertTrue(new File(filepath).exists());
    }

    @When("^I load stored xml file$")
    public void iLoadStoredXmlFile() throws Exception {
        bufferedReader = new BufferedReader(new FileReader(filepath));
    }

    @Then("^File should not be empty$")
    public void fileShouldNotBeEmpty() throws Exception {
        assertNotNull(bufferedReader.readLine());
        bufferedReader.close();
    }

    @And("^XML file should contain my event tree$")
    public void xmlFileShouldContainMyEventTree() throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        Document doc = factory.newDocumentBuilder().parse(new File(filepath));

        XPathFactory xFactory = XPathFactory.newInstance();
        XPath xpath = xFactory.newXPath();
        XPathExpression expr = xpath.compile("//eventTree//description[contains(.,'Drzewo zdarzen')]");
        Object result = expr.evaluate(doc,XPathConstants.NODESET);
        NodeList nodes = (NodeList)result;
        assertTrue(nodes.getLength() > 0);
    }

    @When("^I load an event tree from stored xml file$")
    public void iLoadAnEventTreeFromStoredXmlFile() throws Exception {
        newTree = EventTree.loadFromXML(filepath);
    }

    @And("^New events tree description should be \"([^\"]*)\"$")
    public void newEventsTreeDescriptionShouldBe(String description) throws Exception {
        assertEquals(description, newTree.getDescription());
    }

    @And("^New event tree should be defined with string \"([^\"]*)\"$")
    public void newEventTreeShouldBeDefinedWithString(String eventTreeString) throws Exception {
        assertEquals(eventTreeString, newTree.toString());
    }

    @But("^New event tree should not be defined with string \"([^\"]*)\"$")
    public void newEventTreeShouldNotBeDefinedWithString(String eventTreeString) throws Exception {
        assertFalse(eventTreeString.equals(newTree.toString()));
    }
}




Runner file

File located in safetyanalysis/safety-eventstree/src/test/java/EventTreeAcceptanceTest.java

Example - Run
package pl.wroc.pwr.sa.et;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;

/**
 * Created by Patryk on 11.05.2017.
 */

@RunWith(Cucumber.class)
@CucumberOptions(
        monochrome = true,
        format = { "pretty", "html:target/cucumber" },
        glue = "pl.wroc.pwr.sa.et.steps",
        features = "classpath:cucumber/EventTree.feature"
)
public class EventTreeAT {
}

Test Results

 After run our test we can see in console that it was finished:
 

Below we can see automatically generated report with results of this test. As we can see, everything is green-coloured, which means that test was completed successfully. In other case, red colour will fill all steps that wasn't passed.
This report is located in  safetyanalysis/safety-eventstree/target/cucumber/index.html


Related content

Sytem architecture
Sytem architecture
More like this
Safety Analysis
Safety Analysis
More like this
QualitySpy
QualitySpy
More like this
02. Integration of Acquisition GUI
02. Integration of Acquisition GUI
More like this
Event tree
Event tree
More like this
11. Fault Tree
11. Fault Tree
More like this