All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.android.ddmlib.testrunner.UIAutomatorRemoteAndroidTestRunner Maven / Gradle / Ivy

The newest version!
package com.android.ddmlib.testrunner;

import java.io.IOException;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;

import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.Log;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.TimeoutException;

/**
 * Runs a UI Automator test command remotely and reports results.
 */
public class UIAutomatorRemoteAndroidTestRunner
{

    private IDevice mRemoteDevice;
    // default to no timeout
    private int mMaxTimeToOutputResponse = 0;
    private String mRunName = null;

    /** map of name-value instrumentation argument pairs */
    private List< Entry< String, String >> mArgList;
    private InstrumentationResultParser mParser;
    private final String jarFile;
    private boolean noHup;
    private Object dumpFilePath;

    private static final String LOG_TAG = "RemoteAndroidTest";

    // defined instrumentation argument names
    private static final String CLASS_ARG_NAME = "class";
    private static final String DEBUG_ARG_NAME = "debug";

    public UIAutomatorRemoteAndroidTestRunner( String jarFile, IDevice remoteDevice )
    {
        this.jarFile = jarFile;
        mRemoteDevice = remoteDevice;
        mArgList = new ArrayList< Entry< String, String >>();
    }

    /**
     * {@inheritDoc}
     */

    public void setTestClassOrMethods( String[] testClassOrMethods )
    {
        for ( String testClassOrMethod : testClassOrMethods )
        {
            addInstrumentationArg( CLASS_ARG_NAME, testClassOrMethod );
        }
    }

    /**
     * {@inheritDoc}
     */
    public void addInstrumentationArg( String name, String value )
    {
        if ( name == null || value == null )
        {
            throw new IllegalArgumentException( "name or value arguments cannot be null" );
        }
        mArgList.add( new AbstractMap.SimpleImmutableEntry< String, String >( name, value ) );
    }

    /**
     * {@inheritDoc}
     */

    public void addBooleanArg( String name, boolean value )
    {
        addInstrumentationArg( name, Boolean.toString( value ) );
    }

    /**
     * {@inheritDoc}
     */

    /**
     * {@inheritDoc}
     */

    public void setDebug( boolean debug )
    {
        addBooleanArg( DEBUG_ARG_NAME, debug );
    }

    public void setNoHup( boolean noHup )
    {
        this.noHup = noHup;
    }

    public void setDumpFilePath( String dumpFilePath )
    {
        this.dumpFilePath = dumpFilePath;
    }

    /**
     * {@inheritDoc}
     */

    public void setMaxtimeToOutputResponse( int maxTimeToOutputResponse )
    {
        mMaxTimeToOutputResponse = maxTimeToOutputResponse;
    }

    /**
     * {@inheritDoc}
     */

    public void setRunName( String runName )
    {
        mRunName = runName;
    }

    /**
     * {@inheritDoc}
     */

    public void run( ITestRunListener... listeners ) throws TimeoutException, AdbCommandRejectedException,
            ShellCommandUnresponsiveException, IOException
    {
        run( Arrays.asList( listeners ) );
    }

    /**
     * {@inheritDoc}
     */
    public void run( Collection< ITestRunListener > listeners ) throws TimeoutException, AdbCommandRejectedException,
            ShellCommandUnresponsiveException, IOException
    {
        final String runCaseCommandStr = String.format( "uiautomator runtest %1$s %2$s", jarFile, buildArgsCommand() );
        Log.i( LOG_TAG, String.format( "Running %1$s on %2$s", runCaseCommandStr, mRemoteDevice.getSerialNumber() ) );
        mParser = new InstrumentationResultParser( mRunName, listeners );

        try
        {
            mRemoteDevice.executeShellCommand( runCaseCommandStr, mParser, mMaxTimeToOutputResponse );
        }
        catch ( IOException e )
        {
            Log.w( LOG_TAG, String.format( "IOException %1$s when running tests %2$s on %3$s", e.toString(), jarFile,
                    mRemoteDevice.getSerialNumber() ) );
            // rely on parser to communicate results to listeners
            mParser.handleTestRunFailed( e.toString() );
            throw e;
        }
        catch ( ShellCommandUnresponsiveException e )
        {
            Log.w( LOG_TAG,
                    String.format( "ShellCommandUnresponsiveException %1$s when running tests %2$s on %3$s",
                            e.toString(), jarFile, mRemoteDevice.getSerialNumber() ) );
            mParser.handleTestRunFailed( String.format( "Failed to receive adb shell test output within %1$d ms. "
                    + "Test may have timed out, or adb connection to device became unresponsive",
                    mMaxTimeToOutputResponse ) );
            throw e;
        }
        catch ( TimeoutException e )
        {
            Log.w( LOG_TAG,
                    String.format( "TimeoutException when running tests %1$s on %2$s", jarFile,
                            mRemoteDevice.getSerialNumber() ) );
            mParser.handleTestRunFailed( e.toString() );
            throw e;
        }
        catch ( AdbCommandRejectedException e )
        {
            Log.w( LOG_TAG, String.format( "AdbCommandRejectedException %1$s when running tests %2$s on %3$s",
                    e.toString(), jarFile, mRemoteDevice.getSerialNumber() ) );
            mParser.handleTestRunFailed( e.toString() );
            throw e;
        }
    }

    /**
     * {@inheritDoc}
     */
    public void cancel()
    {
        if ( mParser != null )
        {
            mParser.cancel();
        }
    }

    /**
     * Returns the full instrumentation command line syntax for the provided instrumentation arguments. Returns an empty
     * string if no arguments were specified.
     */
    private String buildArgsCommand()
    {
        StringBuilder commandBuilder = new StringBuilder();
        for ( Entry< String, String > argPair : mArgList )
        {
            final String argCmd = String.format( " -e %1$s %2$s", argPair.getKey(), argPair.getValue() );
            commandBuilder.append( argCmd );
        }

        if ( noHup )
        {
            commandBuilder.append( " --nohup" );
        }

        if ( dumpFilePath != null )
        {
            commandBuilder.append( " dump " + dumpFilePath );
        }
        return commandBuilder.toString();
    }
    
    /**
     * Adds instrumentation arguments from userProperties from keys with the propertiesKeyPrefix prefix.
     * 
     * @param userProperties
     * @param propertiesKeyPrefix
     */
    public void setUserProperties( Properties userProperties, String propertiesKeyPrefix )
    {
        if ( userProperties == null )
        {
            throw new IllegalArgumentException( "userProperties  cannot be null" );
        }
        
        if ( StringUtils.isBlank( propertiesKeyPrefix ) )
        {
            //propertiesPrefix is blank, ignore all properties
            return;
        }
        
        for ( Entry< Object, Object > property : userProperties.entrySet() )
        {
            String name = (String) property.getKey();
            
            //Check if the key starts with the parameterPrefix
            if ( StringUtils.startsWith( name, propertiesKeyPrefix ) )
            {
                String value = (String) property.getValue();
                
                //Remove the prefix
                name = StringUtils.substring( name,
                        StringUtils.length( propertiesKeyPrefix ),
                        StringUtils.length( name ) );
                
                // Verify so the key isn't blank after substring
                if ( StringUtils.isNotBlank( name ) )
                {
                    //Now its safe to add the parameter
                    addInstrumentationArg( name, value );
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy