diff --git a/app/build.gradle b/app/build.gradle index 3373ede..7ecbd7d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -119,6 +119,9 @@ dependencies { androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion" androidTestImplementation "androidx.test.ext:junit:$androidxTest" androidTestImplementation "androidx.test:rules:$androidxTestRules" + //cocoumber + androidTestImplementation 'io.cucumber:cucumber-android:7.3.1' + androidTestImplementation 'io.cucumber:cucumber-junit:7.3.1' } apply from: '../spotless.gradle' diff --git a/app/src/test-common/CocumberTestRunner.kt b/app/src/test-common/CocumberTestRunner.kt new file mode 100644 index 0000000..05b0a37 --- /dev/null +++ b/app/src/test-common/CocumberTestRunner.kt @@ -0,0 +1,10 @@ +import cucumber.api.CucumberOptions +import cucumber.api.junit.Cucumber +import org.junit.runner.RunWith + +@RunWith(Cucumber::class) +@CucumberOptions( + features = ["features"], + glue = ["com.skydoves.themovies.test"] +) +class CucumberTestRunner diff --git a/app/src/test/java/com/skydoves/themovies/viewmodel/MoviesAppBehaviourTest.kt b/app/src/test/java/com/skydoves/themovies/viewmodel/MoviesAppBehaviourTest.kt new file mode 100644 index 0000000..80f574d --- /dev/null +++ b/app/src/test/java/com/skydoves/themovies/viewmodel/MoviesAppBehaviourTest.kt @@ -0,0 +1,89 @@ +import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.LargeTest +import androidx.test.rule.ActivityTestRule + +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +import com.example.movies.MainActivity +import com.example.movies.R + +@RunWith(AndroidJUnit4::class) +@LargeTest +class MoviesAppBehaviourTest { + + @Rule + @JvmField + var mActivityRule: ActivityTestRule = ActivityTestRule(MainActivity::class.java) + + @Test + fun navigateToMovieDetailsScreen() { + // Perform an action to navigate to the details screen + Espresso.onView(ViewMatchers.withId(R.id.movies_list)) + .perform(ViewActions.click()) + + // Assert that the details screen is displayed + Espresso.onView(ViewMatchers.withId(R.id.movie_details)) + .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + } + + @Test + fun applyYearFilter() { + // Perform an action to apply the year filter + Espresso.onView(ViewMatchers.withId(R.id.year_filter_button)) + .perform(ViewActions.click()) + + // Assume the year filter dialog is displayed, select a specific year + Espresso.onView(ViewMatchers.withId(R.id.year_filter_dialog)) + .perform(ViewActions.click()) + + // Assert that the movie list is updated with the filtered results + Espresso.onView(ViewMatchers.withId(R.id.movies_list)) + .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + + // Assert that the filtered movies meet the specified criteria + Espresso.onView(ViewMatchers.withId(R.id.movies_list)) + .check { view, _ -> + // Custom assertions on the filtered movies + val movieList = view as RecyclerView + val adapter = movieList.adapter as MovieListAdapter + for (i in 0 until adapter.itemCount) { + val movie = adapter.getItem(i) + Assert.assertTrue(movie.year == selectedYear) + } + } + } + + @Test + fun applyPopularityFilter() { + // Perform an action to apply the popularity filter + Espresso.onView(ViewMatchers.withId(R.id.popularity_filter_button)) + .perform(ViewActions.click()) + + // Assume the popularity filter dialog is displayed, select a specific popularity range + Espresso.onView(ViewMatchers.withId(R.id.popularity_filter_dialog)) + .perform(ViewActions.click()) + + // Assert that the movie list is updated with the filtered results + Espresso.onView(ViewMatchers.withId(R.id.movies_list)) + .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + + // Assert that the filtered movies meet the specified criteria + Espresso.onView(ViewMatchers.withId(R.id.movies_list)) + .check { view, _ -> + // Custom assertions on the filtered movies + val movieList = view as RecyclerView + val adapter = movieList.adapter as MovieListAdapter + for (i in 0 until adapter.itemCount) { + val movie = adapter.getItem(i) + Assert.assertTrue(movie.popularity >= minPopularity && movie.popularity <= maxPopularity) + } + } + } + +} \ No newline at end of file diff --git a/app/src/test/java/com/skydoves/themovies/viewmodel/MoviesSteps.kt b/app/src/test/java/com/skydoves/themovies/viewmodel/MoviesSteps.kt new file mode 100644 index 0000000..e0b969b --- /dev/null +++ b/app/src/test/java/com/skydoves/themovies/viewmodel/MoviesSteps.kt @@ -0,0 +1,66 @@ +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.* +import cucumber.api.java.en.Given +import cucumber.api.java.en.Then +import cucumber.api.java.en.When +import org.junit.Assert + +class MoviesSteps { + + @Given("^I am on the main movies list screen$") + fun iAmOnMainMoviesListScreen() { + // Add any setup code here if needed + } + + @When("^I tap on a movie$") + fun iTapOnAMovie() { + onView(withId(R.id.movies_list)).perform(click()) + } + + @Then("^I should see the movie details screen$") + fun iShouldSeeTheMovieDetailsScreen() { + onView(withId(R.id.movie_details)).check(matches(isDisplayed())) + } + + @When("^I apply a year filter$") + fun iApplyAYearFilter() { + onView(withId(R.id.year_filter_button)).perform(click()) + // Assume the year filter dialog is displayed, select a specific year + onView(withId(R.id.year_filter_dialog)).perform(click()) + } + + @Then("^I should see only movies from the selected year$") + fun iShouldSeeOnlyMoviesFromSelectedYear() { + onView(withId(R.id.movies_list)).check { view, _ -> + // Custom assertions on the filtered movies + val movieList = view as RecyclerView + val adapter = movieList.adapter as MovieListAdapter + for (i in 0 until adapter.itemCount) { + val movie = adapter.getItem(i) + Assert.assertTrue(movie.year == selectedYear) + } + } + } + + @When("^I apply a popularity filter$") + fun iApplyAPopularityFilter() { + onView(withId(R.id.popularity_filter_button)).perform(click()) + // Assume the popularity filter dialog is displayed, select a specific popularity range + onView(withId(R.id.popularity_filter_dialog)).perform(click()) + } + + @Then("^I should see only movies within the specified popularity range$") + fun iShouldSeeOnlyMoviesWithinSpecifiedPopularityRange() { + onView(withId(R.id.movies_list)).check { view, _ -> + // Custom assertions on the filtered movies + val movieList = view as RecyclerView + val adapter = movieList.adapter as MovieListAdapter + for (i in 0 until adapter.itemCount) { + val movie = adapter.getItem(i) + Assert.assertTrue(movie.popularity >= minPopularity && movie.popularity <= maxPopularity) + } + } + } +} \ No newline at end of file diff --git a/app/src/test/resources/movies.features b/app/src/test/resources/movies.features new file mode 100644 index 0000000..420a9c7 --- /dev/null +++ b/app/src/test/resources/movies.features @@ -0,0 +1,16 @@ +Feature: Movies App + + Scenario: Navigate to movie details screen + Given I am on the main movies list screen + When I tap on a movie + Then I should see the movie details screen + + Scenario: Apply year filter + Given I am on the main movies list screen + When I apply a year filter + Then I should see only movies from the selected year + + Scenario: Apply popularity filter + Given I am on the main movies list screen + When I apply a popularity filter + Then I should see only movies within the specified popularity range