cucumber / cucumber-android

Android support for Cucumber-JVM
MIT License
135 stars 62 forks source link

Being able to swap out certain dependencies for individual scenarios #135

Open skadyrov opened 4 weeks ago

skadyrov commented 4 weeks ago

πŸ€” What's the problem you're trying to solve?

I have a Hilt integration with Cucumber, and I want to run scenarios with certain "test" versions of some dependencies. Let's say, I have a CountryRepository like below:

@Module
@InstallIn(SingletonComponent::class)
abstract class CountryModule {

    @Binds
    abstract fun bindCountryRepository(impl: DefaultCountryRepository): CountryRepository
}

interface CountryRepository {
    fun getCountry(): String
}

@Singleton
class DefaultCountryRepository @Inject constructor(): CountryRepository {
    override fun getCountry(): String {
        return "us"
    }
}

I'd like to run the following tests:

## using DefaultCountryRepository
@wip
  Scenario: correct rows are displayed when content is launched in USA
    Given app is launched in USA
    When user goes to home tab
    Then rows are displayed correctly
## using GermanyRepository
  @wip
  Scenario: correct rows are displayed when content is launched in Germany
    Given app is launched in Germany
    When user goes to home tab
    Then rows are displayed correctly

And my "test" dependency:

class GermanyRepository @Inject constructor(): CountryRepository {
    override fun getCountry(): String {
        return "germany"
    }
}

It appears that I can't swap DefaultCountryRepository with my test repositories on demand in each scenario.

✨ What's your proposed solution?

It would be great to allow replacing certain dependencies in each scenarios. Using Hilt without cucumber, I'd be able to do it like this:


@UninstallModules(CountryModule::class)
@HiltAndroidTest
class HiltExampleTestWithGermany {

    @Module
    @InstallIn(SingletonComponent::class)
    abstract class CountryModule {

        @Singleton
        @Binds
        abstract fun bindCountryRepository(
            repository: GermanyRepository
        ): CountryRepository
    }

    @Rule
    @JvmField
    val hiltRule = HiltAndroidRule(this)
}

This way, I could create as many test classes as this, each of them would be isolated from each other. My app would be executed running that specific dependency in my test.

⛏ Have you considered any alternatives or workarounds?

No, if there is any way to achieve this that I am not aware of, please advise me.

πŸ“š Any additional context?

Generally, I am facing this issue with feature-flagged parts of my app. Some features are enabled in some countries, or based on other configurations. I want to have a better control of those environments in my BDD tests.

skadyrov commented 4 weeks ago

Maybe an alternative question is: Is it generally considered a good approach to test the behavior in different environments by faking some dependencies?