I've been trying to get Selenium tests setup on Heroku. However, I've observed that when even a small test runs, Heroku throws R14 errors due to memory consumption.
I started trying to run these tests using free dynos and have upgraded up to the Standard 2X dynos and still see this issue. I can't imagine that these tests require more than 1GB of RAM to run. I suppose it's possible but I was interested in hearing other people's experiences with this and to see if anyone ran into similar issues and had solutions.
Locally the tests are super speedy and run fine. I know on the Heroku side that the buildpacks need to dynamically download chrome and the driver each time the tests are run so a little slowness there is to be expected.
A couple notes about my process:
- I'm using the Gradle wrapper to run the test script
- I'm running the Selenium test via the jUnit framework
- I'm using the
heroku/google-chromeandheroku/chromedriverbuildpacks
Here's my setup so you can see if I'm doing anything strange...
SeleniumConfig.kt
class SeleniumConfig {
val driver: WebDriver
init {
val options = ChromeOptions()
val driverFile = System.getenv("CHROME_DRIVER_PATH")
val binary = System.getenv("GOOGLE_CHROME_BIN")
options.apply {
addArguments("--enable-javascript")
addArguments("--start-maximized")
addArguments("--incognito")
addArguments("--headless")
addArguments("--disable-gpu")
addArguments("--no-sandbox")
}
val service = ChromeDriverService.Builder()
.usingDriverExecutable(File(driverFile))
.build()
binary?.let { options.setBinary(it) }
driver = ChromeDriver(service, options)
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS)
}
}
BaseSeleniumTest.kt
open class BaseSeleniumTest(private val path: String) {
companion object {
const val DEFAULT_WAIT = 5000L
}
protected val config = SeleniumConfig()
protected val driver: WebDriver
get() = config.driver
@BeforeEach
fun setUp() {
driver.get("https://<mysite>$path")
implicitWait()
}
@AfterEach
fun tearDown() {
driver.close()
driver.quit()
}
fun implicitWait() {
driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT, TimeUnit.MILLISECONDS)
}
}
SigninTest.kt
class SigninTest : BaseSeleniumTest("/signin") {
@Test
fun `Succeed signing in`() {
val username = driver.findElement(By.name("email"))
val password = driver.findElement(By.name("password"))
username.sendKeys("test@test.com")
password.sendKeys("password")
username.submit()
implicitWait()
}
@Test
fun `Fail with invalid username`() {
val username = driver.findElement(By.name("email"))
val password = driver.findElement(By.name("password"))
username.sendKeys("wrong")
password.sendKeys("password")
username.submit()
implicitWait()
assertEquals("Invalid email or password",
driver.findElement(By.cssSelector(".form-error")).text)
}
@Test
fun `Fail with invalid password`() {
val username = driver.findElement(By.name("email"))
val password = driver.findElement(By.name("password"))
username.sendKeys("test@test.com")
password.sendKeys("wrong")
username.submit()
implicitWait()
assertEquals("Invalid email or password",
driver.findElement(By.cssSelector(".form-error")).text)
}
}
Any help that anyone could give me would be appreciated!