Skip to content

Offer to Contribute Reproducible Test Case for Previously Reported Bug #923

@Software-Testing600

Description

@Software-Testing600

Hello!

I saw that the app previously had a bug (issue #615). I created a test (based on that version of the app) to help ensuring that the issue does not happen again. In other words, the test could be used for regression testing.

Would it be helpful if I contributed this test to your codebase? I’d be happy to open a pull request for the latest version, integrating the test with your existing test infrastructure.

Additionally, I’ve created similar regression tests for 3 other issues in the repository that I would also be happy to integrate if it would be helpful.

You can find the script for issue #615 below:


import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;

import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import androidx.test.filters.SdkSuppress;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;

import java.util.concurrent.TimeUnit;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

/**
 * Regression test for Gnucash (org.gnucash.android).
 * Verifies handling of uninitialized export timestamps.
 */
@RunWith(AndroidJUnit4.class)
@SdkSuppress(minSdkVersion = 18)
public class GnucashLastExportDateTest {

    private static final String BASIC_SAMPLE_PACKAGE = "org.gnucash.android";
    private static final String INSTALLER_PACKAGE = "com.android.packageinstaller";
    private static final int LAUNCH_TIMEOUT = 5000;

    private UiDevice mDevice;

    @Before
    public void startMainActivityFromHomeScreen() {
        mDevice = UiDevice.getInstance(getInstrumentation());

        mDevice.pressHome();

        final String launcherPackage = getLauncherPackageName();
        assertThat(launcherPackage, notNullValue());
        mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);

        Context context = getApplicationContext();
        final Intent intent = context.getPackageManager()
                .getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        context.startActivity(intent);

        mDevice.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT);
    }

    @Test
    public void testChangeText_sameActivity() {
        // Walk through the initial setup wizard
        UiObject2 nextButton = mDevice.wait(Until.findObject(By.res(BASIC_SAMPLE_PACKAGE, "btn_save")), 1000);
        nextButton.click();
        nextButton.click();

        UiObject2 setupButton = mDevice.wait(Until.findObject(By.text("Let me handle it")), 1000);
        setupButton.click();

        nextButton.click();

        UiObject2 disableCrashReports = mDevice.wait(Until.findObject(By.text("Disable crash reports")), 1000);
        disableCrashReports.click();

        UiObject2 finalNextButton = mDevice.wait(Until.findObject(By.res(BASIC_SAMPLE_PACKAGE, "btn_save")), 1000);
        finalNextButton.click();

        UiObject2 doneButton = mDevice.wait(Until.findObject(By.text("DONE")), 1000);
        doneButton.click();

        // Allow permissions
        UiObject2 allowButton = mDevice.wait(Until.findObject(By.res(INSTALLER_PACKAGE, "permission_allow_button")), 1000);
        allowButton.click();

        // Wait for main activity to stabilize
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // Relaunch to avoid UI inconsistencies
        startMainActivityFromHomeScreen();

        // Open navigation drawer and select book
        UiObject2 menuButton = mDevice.wait(Until.findObject(By.desc("Navigation drawer opened")), 1000);
        menuButton.click();

        UiObject2 bookItem = mDevice.wait(Until.findObject(By.res(BASIC_SAMPLE_PACKAGE, "book_name")), 2000);
        bookItem.click();

        // Navigate to "Manage Books"
        UiObject2 manageBooks = mDevice.wait(Until.findObject(By.text("Manage Books…")), 2000);
        manageBooks.click();

        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // === Assertion Section ===

        UiDevice uiDevice = UiDevice.getInstance(getInstrumentation());

        // Element: label for "last sync"
        UiObject2 lastSyncLabel = uiDevice.findObject(By.res("org.gnucash.android:id/label_last_sync"));

        // Element: text value of last sync
        UiObject2 lastSyncTime = uiDevice.findObject(By.res("org.gnucash.android:id/last_sync_time"));

        // Assert the default invalid sync time is not shown
        assertFalse(lastSyncTime.getText().equals("1969-12-31 18:00:00.0"));
    }

    /**
     * Dynamically retrieves the current launcher app's package name.
     */
    private String getLauncherPackageName() {
        final Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        PackageManager pm = getApplicationContext().getPackageManager();
        ResolveInfo resolveInfo = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
        return resolveInfo.activityInfo.packageName;
    }
}

Please let me know if you're open to this or if there are any contribution guidelines I should follow.

Thanks for your work on this project!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions