# Buggy code
def check_app_installed(self):
    """Overrides superclass."""
    # Check that the Mobly Snippet app is installed.
    if not self._adb_grep_wrapper(
        r'pm list package | tr -d "\r" | grep "^package:%s$"' % self.package
    ):
        raise jsonrpc_client_base.AppStartError(
            "%s is not installed on %s" % (self.package, self._serial)
        )
    # Check that the app is instrumented.
    out = self._adb_grep_wrapper(
        r'pm list instrumentation | tr -d "\r" | grep ^instrumentation:%s/%s'
        % (self.package, _INSTRUMENTATION_RUNNER_PACKAGE)
    )
    if not out:
        raise jsonrpc_client_base.AppStartError(
            "%s is installed on %s, but it is not instrumented."
            % (self.package, self._serial)
        )
    match = re.search(r"^instrumentation:(.*)\/(.*) \(target=(.*)\)$", out)
    target_name = match.group(3)
    # Check that the instrumentation target is installed if it's not the
    # same as the snippet package.
    if target_name != self.package:
        out = self._adb_grep_wrapper(
            r'pm list package | tr -d "\r" | grep ^package:%s$' % target_name
        )
        if not out:
            raise jsonrpc_client_base.AppStartError(
                "Instrumentation target %s is not installed on %s"
                % (target_name, self._serial)
            )


# Traceback (AttributeError)
$ snippet_shell.py com.google.android.mobly.snippet.bundled
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/bin/snippet_shell.py", line 6, in <module>
exec(compile(open(__file__).read(), __file__, 'exec'))
File "/Users/angli/Developer/mobly/tools/snippet_shell.py", line 64, in <module>
SnippetShell(args.package[0]).main(args.serial)
File "/Users/angli/Developer/mobly/mobly/controllers/android_device_lib/jsonrpc_shell_base.py", line 91, in main
self.start_console()
File "/Users/angli/Developer/mobly/mobly/controllers/android_device_lib/jsonrpc_shell_base.py", line 76, in start_console
self._start_services(console_env)
File "/Users/angli/Developer/mobly/tools/snippet_shell.py", line 41, in _start_services
self._ad.load_snippet(name='snippet', package=self._package)
File "/Users/angli/Developer/mobly/mobly/controllers/android_device.py", line 629, in load_snippet
self._start_jsonrpc_client(client)
File "/Users/angli/Developer/mobly/mobly/controllers/android_device.py", line 660, in _start_jsonrpc_client
client.check_app_installed()
File "/Users/angli/Developer/mobly/mobly/controllers/android_device_lib/snippet_client.py", line 110, in check_app_installed
target_name = match.group(3)
AttributeError: 'NoneType' object has no attribute 'group'

# Fixed code
def check_app_installed(self):
    """Overrides superclass."""
    # Check that the Mobly Snippet app is installed.
    out = self._adb.shell("pm list package")
    if not self._grep("^package:%s$" % self.package, out):
        raise jsonrpc_client_base.AppStartError(
            "%s is not installed on %s" % (self.package, self._serial)
        )
    # Check that the app is instrumented.
    out = self._adb.shell("pm list instrumentation")
    matched_out = self._grep(
        "^instrumentation:%s/%s" % (self.package, _INSTRUMENTATION_RUNNER_PACKAGE), out
    )
    if not matched_out:
        raise jsonrpc_client_base.AppStartError(
            "%s is installed on %s, but it is not instrumented."
            % (self.package, self._serial)
        )
    match = re.search("^instrumentation:(.*)\/(.*) \(target=(.*)\)$", matched_out[0])
    target_name = match.group(3)
    # Check that the instrumentation target is installed if it's not the
    # same as the snippet package.
    if target_name != self.package:
        out = self._adb.shell("pm list package")
        if not self._grep("^package:%s$" % target_name, out):
            raise jsonrpc_client_base.AppStartError(
                "Instrumentation target %s is not installed on %s"
                % (target_name, self._serial)
            )