Driver is alway Null?

Hi I’m a uni student doing my dissertation on Appium. I’m fairly new to it and I have been struggling to get a test to pass for months. When I run the following test, the driver isn’t initialised and is set to null. I don’t know what I’m doing wrong.

AppiumTest.java:

package com.example.singleactionapp;


import org.junit.Assert;
import org.junit.Test;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.openqa.selenium.WebElement;

import io.appium.java_client.AppiumBy;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;

import java.net.URL;

public class AppiumTest {
    public static AndroidDriver driver;

    @BeforeEach
    public void setup () throws Exception {
        UiAutomator2Options options = new UiAutomator2Options()
                .setUdid("emulator-5554")
                .setDeviceName("Pixel 7 API 34")
                .setApp("/SingleActionApp.apk");
        driver = new AndroidDriver(
                // The default URL in Appium 1 is http://127.0.0.1:4723/wd/hub
                new URL("http://127.0.0.1:4723"), options
        );
    }

    @Test
    public void ButtonTest () {
        System.out.println("In Test Case ButtonTest");
        System.out.println("Driver:" + driver);
        WebElement button = driver.findElement(AppiumBy.id("buttonID"));
        button.click();
        WebElement message = driver.findElement(AppiumBy.id("messageID"));
        Assert.assertEquals(message.getText(), "Button has been pressed 1 time");
    }

    @AfterEach
    public void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }
}

I’ve attached the build.gradle file below as well just in case.

import com.android.build.api.dsl.Packaging

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

android {
    namespace = "com.example.singleactionapp"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.singleactionapp"
        minSdk = 33
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary = true
        }
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }
    packaging {
        resources {
            excludes.add("/META-INF/{AL2.0,LGPL2.1}")
            excludes.add("/META-INF/LICENSE-notice.md")
            pickFirsts.add("META-INF/LICENSE.md")
            excludes.add("META_INF/INDEX.LIST")
            pickFirsts.add("META-INF/INDEX.LIST")
            excludes.add("META-INF/io.netty.versions.properties")
            pickFirsts.add("META-INF/io.netty.versions.properties")
        }
    }
}

dependencies {
    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
    implementation("androidx.activity:activity-compose:1.8.2")
    implementation(platform("androidx.compose:compose-bom:2023.08.00"))
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.ui:ui-graphics")
    implementation("androidx.compose.ui:ui-tooling-preview")
    implementation("androidx.compose.material3:material3")
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("io.appium:java-client:9.2.0")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    androidTestImplementation(platform("androidx.compose:compose-bom:2023.08.00"))
    androidTestImplementation("androidx.compose.ui:ui-test-junit4")
    androidTestImplementation("org.junit.jupiter:junit-jupiter:5.8.1")
    debugImplementation("androidx.compose.ui:ui-tooling")
    debugImplementation("androidx.compose.ui:ui-test-manifest")
}

Other Details:
Appium Java-Client: 9.2.0
Appium v2.5.4
IDE: Android Studio Iguana

Can you post the server log?

Make sure you use Junit5 to run your suite to properly recognize BeforeEach/AfterEach annotations. Also, the driver property should not be static. See https://www.baeldung.com/junit-before-beforeclass-beforeeach-beforeall

There is no code how you start appium server. Manually?

I only get the default information after starting the appium server. To my understanding, there is absolutely no connection between the test file and the server…

Yup, I run appium in terminal before running this file

  1. What Appium server writing in logs?
    e.g. mine
[Appium] Welcome to Appium v2.5.1
...
[Appium] AndroidUiautomator2Driver has been successfully loaded in 2.968s
[Appium] XCUITestDriver has been successfully loaded in 2.968s
[Appium] Appium REST http interface listener started on http://0.0.0.0:4723
[Appium] You can provide the following URLs in your client code to connect to this server:
[Appium] 	http://127.0.0.1:4723/ (only accessible from the same host)
[Appium] 	http://10.5.31.155:4723/
[Appium] 	http://10.5.61.34:4723/
[Appium] 	http://169.254.203.235:4723/
[Appium] Available drivers:
[Appium]   - [email protected] (automationName 'UiAutomator2')
[Appium]   - [email protected] (automationName 'XCUITest')
[Appium] Available plugins:
[Appium]   - [email protected]
  1. tried replace new URL("http://127.0.0.1:4723")new URL("http://localhost:4723") ?

These are my server logs:

[Appium] Welcome to Appium v2.5.4
...
[Appium] EspressoDriver has been successfully loaded in 5.018s
[Appium] AndroidUiautomator2Driver has been successfully loaded in 5.019s
[Appium] Appium REST http interface listener started on http://0.0.0.0:4723
[Appium] You can provide the following URLs in your client code to connect to this server:
[Appium]        http://127.0.0.1:4723/ (only accessible from the same host)
[Appium]        http://10.121.6.29:4723/
[Appium] Available drivers:
[Appium]   - [email protected] (automationName 'UiAutomator2')
[Appium]   - [email protected] (automationName 'Espresso')
[Appium] No plugins have been installed. Use the "appium plugin" command to install the one(s) you want to use.

  1. I tried replacing 127.0.0.1 to localhost but that didn’t make a difference :confused:
  1. why not try to update uiAutomator driver?
appium driver uninstall uiautomator2
// then
appium driver install uiautomator2
  1. Also check and update (if needed) in Android studio: SDK Platforms and tools
  2. Check in browser that http://127.0.0.1:4723/status shows →
{
  "value": {
    "ready": true,
    "message": "The server is ready to accept new connections",
    "build": {
      "version": "2.5.1"
    }
  }
}
  1. I updated UIAutomator2 and got the same message when running http://127.0.0.1:4723/status - thank you for that!
  2. I have Android 14, API 34 already installed.

I’ve just added my code again because I made a few adjustments:

package com.example.singleactionapp;


import org.junit.Assert;
import org.junit.Test;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.openqa.selenium.WebElement;

import io.appium.java_client.AppiumBy;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;

import java.net.URL;

public class AppiumTest {
    public AndroidDriver driver;

    @BeforeAll
    public void setup () throws Exception {
        UiAutomator2Options options = new UiAutomator2Options()
                .setUdid("emulator-5554")
                .setDeviceName("Pixel 7 API 34")
                .setApp("/AndroidStudioProjects/SingleActionApp.apk");
        driver = new AndroidDriver(
                // The default URL in Appium 1 is http://127.0.0.1:4723/wd/hub
                new URL("http://localhost:4723"), options
        );
    }

    @Test
    public void ButtonTest () {
        System.out.println("In Test Case ButtonTest");
        System.out.println("Driver:" + driver);
        WebElement button = driver.findElement(AppiumBy.id("buttonID"));
        button.click();
        WebElement message = driver.findElement(AppiumBy.id("messageID"));
        Assert.assertEquals(message.getText(), "Button has been pressed 1 time");
    }

    @AfterAll
    public void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }
}

and this is the error message I keep getting:

java.lang.NullPointerException: Attempt to invoke virtual method 'org.openqa.selenium.WebElement io.appium.java_client.android.AndroidDriver.findElement(org.openqa.selenium.By)' on a null object reference
at com.example.singleactionapp.AppiumTest.ButtonTest(AppiumTest.java:35)

The print statement System.out.println("Driver:" + driver); prints out Driver:null

  1. try:
public AndroidDriver driver;
->
public static AndroidDriver driver;

Unfortunately, that does not work as well.

Furthermore, could you please check if my build.gradle file and test file are both correctly using JUnit 5?

build.gradle:

import com.android.build.api.dsl.Packaging

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("de.mannodermaus.android-junit5") version "1.10.0.0"
}

android {
    namespace = "com.example.singleactionapp"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.singleactionapp"
        minSdk = 33
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        testInstrumentationRunnerArguments["runnerBuilder"]="de.mannodermaus.junit5.AndroidJUnit5Builder"
        vectorDrawables {
            useSupportLibrary = true
        }
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
    kotlinOptions {
        jvmTarget = "11"
    }
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }
    packaging {
        resources {
            excludes.add("/META-INF/{AL2.0,LGPL2.1}")
            excludes.add("/META-INF/LICENSE-notice.md")
            pickFirsts.add("META-INF/LICENSE.md")
            excludes.add("META_INF/INDEX.LIST")
            pickFirsts.add("META-INF/INDEX.LIST")
            excludes.add("META-INF/io.netty.versions.properties")
            pickFirsts.add("META-INF/io.netty.versions.properties")
        }
    }
}

dependencies {
    implementation("androidx.core:core-ktx:1.13.1")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
    implementation("androidx.activity:activity-compose:1.9.0")
    implementation(platform("androidx.compose:compose-bom:2024.05.00"))
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.ui:ui-graphics")
    implementation("androidx.compose.ui:ui-tooling-preview")
    implementation("androidx.compose.material3:material3")
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    testImplementation ("org.junit.jupiter:junit-jupiter-api:5.9.2")
    testRuntimeOnly ("org.junit.jupiter:junit-jupiter-engine:5.9.2")
    //noinspection GradleDependency
    androidTestImplementation("io.appium:java-client:9.2.0")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    androidTestImplementation(platform("androidx.compose:compose-bom:2024.05.00"))
    androidTestImplementation("androidx.compose.ui:ui-test-junit4")
    androidTestImplementation ("org.junit.jupiter:junit-jupiter-api:5.9.2")
    androidTestRuntimeOnly ("org.junit.jupiter:junit-jupiter-engine:5.9.2")
    androidTestImplementation ("org.junit.jupiter:junit-jupiter-params:5.9.2")
    debugImplementation("androidx.compose.ui:ui-tooling")
    debugImplementation("androidx.compose.ui:ui-test-manifest")
}

appiumTest.java - (And just to be clear, this is saved in the androidTest folder?)

package com.example.singleactionapp;


import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.openqa.selenium.WebElement;

import io.appium.java_client.AppiumBy;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;

import java.net.URL;

public class AppiumTest {
    public static AndroidDriver driver;

    @BeforeAll

    public static void setup() throws Exception {
        UiAutomator2Options options = new UiAutomator2Options()
                .setUdid("emulator-5554")
                .setDeviceName("Pixel 7 API 34")
                .setApp("/Users/dimashafernando/AndroidStudioProjects/SingleActionApp.apk");
        driver = new AndroidDriver(
                // The default URL in Appium 1 is http://127.0.0.1:4723/wd/hub
                new URL("http://127.0.0.1:4723"), options
        );
    }

    @Test
    public void ButtonTest () {
        System.out.println("In Test Case ButtonTest");
        System.out.println("Driver:" + driver);
        WebElement button = driver.findElement(AppiumBy.id("buttonID"));
        button.click();
        WebElement message = driver.findElement(AppiumBy.id("messageID"));
        Assertions.assertEquals(message.getText(), "Button has been pressed 1 time");
    }

    @AfterAll
    public static void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }
}