SkySync-EPFL / skysync

1 stars 0 forks source link

SkySync

product vision

An application that simplifies and optimizes staff interactions and planning in a hot air baloon enterprise.

Links

Roles

Each user is assigned a primary authentication role, such as crew, pilot, or admin. Additionally, users may temporarily acquire supplementary roles, such as maitre fondu during a flight, which should not expand their permissions.

These roles are stored in the database.

Auth Crew

Crew members are responsible for preparing the flight, (includes arranging equipment and food for the journey). During the flight, they either follow the balloon in a vehicle or remain inside to cater to the passengers. After the theft, they are responsible for storing the equipment.. read have access to their personal data and to information relating to the flight to which they are assigned.

Auth Pilot

Pilots are the only ones legally entitled to drive a hot-air balloon. They are responsible for specialized equipment if required (high-altitude flight). Pilots have read access to their personal data and to information relating to the flight to which they are assigned.

Auth Admin

Administrators create flights and assign staff to them. They have read/write acccess to everything.

Other roles

TBD

Database

SkySync database diagram

Architecture Diagram

SwEnt Architecture Diagram

Data Models

Screenshot 2024-04-11 at 17 35 25

Testing

Firebase emulators

We use emulators to integrate Firebase products in the tests.

To run the tests that use the emulators locally, you need to setup the emulators:

[!NOTE] Tests using the Firebase emulators need to be UI tests, they need to run on the Android emulator.

UI Testing: Global Description

Here is the official documentation: https://developer.android.com/develop/ui/compose/testing#isolation

Here is the cheatsheet: https://developer.android.com/develop/ui/compose/testing-cheatsheet

There are 2 methods. An easier one, which I recommend, and a more complicated one which requires creating 2 classes for more elaborate tests.

First method

Find the component to test

If the component has a unique text identifier, you can use it to test it. Assume I have a button that goes back on click in the class ChatScreen.kt.

Button(onClick = "go Back", Text = "testButton")

If not you can add a test tag on it.

Button(modifier = Modifier.testTag("testButton"), onClick = "go Back")

Create testing class

The name of this class should be nameOfTheClassTest. Create this class where you want. For example you could create a folder Chat and put the ChatScreenTest inside.

class ChatScreenTest : TestCase(kaspressoBuilder = Kaspresso.Builder.withComposeSupport()) {

    //required to test UI components
  @get:Rule val composeTestRule = createComposeRule()

  @Before
  fun testSetup() {
    val vm = ToDoViewModel()
    //here ChatScreen refers to the class in app/src/main/java/ch/epfl/skysync
    composeTestRule.setContent { ChatScreen(vm, mockNavActions) }
  }

  @Test
  fun ButtonIsCorrectlyDisplayedAndhasClickAction() { 
    composeTestRule.onNodeWithText("testButton").assertIsDisplayed()
    composeTestRule.onNodeWithText("testButton").assertHasClickAction()
    composeTestRule.onNodeWithText("testButton").performClick()

    //if using the test tag
    composeTestRule.onNode(hasTestTag("testButton")).assertIsDisplayed()
    composeTestRule.onNode(hasTestTag("testButton")).assertHasClickAction()
    composeTestRule.onNode(hasTestTag("testButton")).performClick()

  }

}

You can find an example testing navigation here app/src/androidTest/java/ch/epfl/skysync

Second method

First you have to add test tags to all components you want to test

Create first (mapping) class

The name of this class should match its counterpart. Make sure a test label is added to the class so that the test can find the location of the tested components. For example if ChatScreen is a Scaffold containg the button add the test tag on the modifier of the Scaffold.

class ChatScreen(semanticsProvider: SemanticsNodeInteractionsProvider) :
    ComposeScreen<ChatScreen>(
      //this test tag must be set on the "top level" component (Scaffold, Surface)
        semanticsProvider = semanticsProvider, viewBuilderAction = { hasTestTag("ChatScreen") }) {

  // Structural elements of the UI
  val testBut: KNode = child { hasTestTag("testButton") }
}

Create second (test) class

The name of this class should be nameOfTheClassTest. Create this class where you want. You could create a folder Chat and put the ChatScreenTest inside.

class ChatScreenTest : TestCase(kaspressoBuilder = Kaspresso.Builder.withComposeSupport()) {

    //required to test UI components
  @get:Rule val composeTestRule = createComposeRule()
    /*
  This rule automatic initializes lateinit properties with @MockK, @RelaxedMockK,
  It gives the mocked class methods default values
    */

  @get:Rule val mockkRule = MockKRule(this)

  @RelaxedMockK lateinit var mockNavActions: NavigationActions

  @Before
  fun testSetup() {
    val vm = ToDoViewModel()
    //here ChatScreen refers to the class in app/src/main/java/ch/epfl/skysync
    composeTestRule.setContent { ChatScreen(vm, mockNavActions) }
  }
  @Test
  fun titleAndButtonAreCorrectlyDisplayed() { run {
    //here ChatScreen refers to the class in app/src/androidTest/java/ch/epfl/skysync
    onComposeScreen<ChatScreen>(composeTestRule) {

    //this has to have the same name as defined in the first class
      testBut {
        //tests if the button is displayed
        assertIsDisplayed()
        //tests if the button can be clicked
        assertHasClickAction()
      }
    }
  }
  }
  @Test
  fun goBackButtonTriggersBackNavigation() = run {
    //here ChatScreen refers to the class in app/src/androidTest/java/ch/epfl/skysync
    onComposeScreen<ChatScreen>(composeTestRule) {
        //this has to have the same name as defined in the first class
      testBut {
        // arrange: verify the pre-conditions
        assertIsDisplayed()
        assertIsEnabled()

        // act: go back !
        performClick()
      }
    }

    // assert: the nav action has been called 
    //go back will return a default value
    verify { mockNavActions.goBack() }
    confirmVerified(mockNavActions)
  }
}

More advanced

* Test that a function was not called (for navigation for example)

```kotlin
verify { mockNavActions wasNot Called }

For more advanced UI testing you can refer to the tests of the bootcamp or online.

Backend tests

Here is how to create a simple unit test

class ExampleUnitTest {

    private val testmyClass: myClass = myClass()
  @Test
  fun addition_isCorrect() {
    val expected = 4
    assertEquals(expected, testmyClass.getFour())
  }
}

You can find an example in app/src/test/java/ch/epfl/skysync/database/schemas.

Jacoco test report

check connectedCheck jacocoTestReport

In order to run connectedCheck you have to launch the emulator. While in the Gradle menu (accessed by clicking on the elephant icon), you can search for tasks by clicking on the terminal icon located directly beneath "Gradle".