2009-09-01 17 views
26

Sono stanco di prendere nuovi screenshot ogni volta che cambio la mia interfaccia utente per la mia applicazione iPhone. Mi piacerebbe essere in grado di eseguire uno script/programma/qualsiasi cosa per caricare il mio binario sul simulatore e quindi fare alcuni screenshot.Automatizza le schermate su iPhone Simulator?

La soluzione può essere in qualsiasi lingua ... non ha importanza per me.

Grazie!

+2

Mi piacerebbe sentire una risposta per farlo anche dal dispositivo. –

risposta

24

Con iPhone SDK 4 è possibile automatizzare i test della GUI e può prendere screenshot per voi.

Fondamentalmente, si scrive uno script Javascript, quindi Strumenti (utilizzando il modello di automazione) possono eseguirlo sul dispositivo per testare l'interfaccia utente e possono registrare dati, schermate, ecc. E anche avvisare se qualcosa è rotto.

Non sono riuscito a trovare una guida di riferimento per questo, ma nella ricerca della libreria di riferimento SDK per le classi UIA* (come UIAElement).

C'è anche un video provare le canzoni di questo dal WWDC, sessione di 306.

+1

Ecco la documentazione di riferimento di Apple: https://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/Built-InInstruments/Built-InInstruments.html#//apple_ref/doc/uid/TP40004652-CH6-SW75 –

6

Il privato UIGetScreenImage(void) API può essere utilizzata per catturare il contenuto dello schermo:

CGImageRef UIGetScreenImage(); 
void SaveScreenImage(NSString *path) 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    CGImageRef cgImage = UIGetScreenImage(); 
    void *imageBytes = NULL; 
    if (cgImage == NULL) { 
     CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 
     imageBytes = malloc(320 * 480 * 4); 
     CGContextRef context = CGBitmapContextCreate(imageBytes, 320, 480, 8, 320 * 4, colorspace, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big); 
     CGColorSpaceRelease(colorspace); 
     for (UIWindow *window in [[UIApplication sharedApplication] windows]) { 
      CGRect bounds = [window bounds]; 
      CALayer *layer = [window layer]; 
      CGContextSaveGState(context); 
      if ([layer contentsAreFlipped]) { 
       CGContextTranslateCTM(context, 0.0f, bounds.size.height); 
       CGContextScaleCTM(context, 1.0f, -1.0f); 
      } 
      [layer renderInContext:(CGContextRef)context]; 
      CGContextRestoreGState(context); 
     } 
     cgImage = CGBitmapContextCreateImage(context); 
     CGContextRelease(context); 
    } 
    NSData *pngData = UIImagePNGRepresentation([UIImage imageWithCGImage:cgImage]); 
    CGImageRelease(cgImage); 
    if (imageBytes) 
     free(imageBytes); 
    [pngData writeToFile:path atomically:YES]; 
    [pool release]; 
} 

ricordarsi di essa all'interno di un #ifdef in modo che non appare nella build di rilascio.

+0

Non riesco a far funzionare il metodo UIGetScreenImage. –

+0

Qual è l'errore? – rpetrich

+0

Sembra che UIGetScreenImage non funzioni più sul simulatore :((l'ultima volta che ho provato era 2.x). Ho aggiornato il codice per includere le basi della cattura dello schermo manuale ... sembra funzionare piuttosto bene con le finestre verticali, non così bene con il panorama e non include la barra di stato, ma è un inizio.Se lo si migliora aggiornare la mia risposta :) – rpetrich

12

Ho lo stesso desiderio. Voglio essere in grado di salvare screenshot da alcune schermate nella mia app senza tutto il lavoro manuale. Non sono ancora arrivato, ma ho iniziato.

L'idea è di tail /var/log/system.log, dove va l'output delle istruzioni NSLog. Conduco l'output a un programma python. Il programma python legge tutte le linee da stdin e quando la linea corrisponde a un modello specifico, chiama screencapture.

NSLog(@"screenshot mainmenu.png"); 

che causerà una schermata denominata "XX. Mainmenu YY.png" da creare ogni volta che viene chiamato. XX è il numero dello screenshot dall'inizio del programma. YY è il numero dello screenshot "mainmenu".

Ho anche aggiunto alcune funzioni inutili:

NSLog(@"screenshot -once mainmenu.png"); 

Ciò farà risparmiare solo "XX mainmenu.png." Una volta.

NSLog(@"screenshot -T 4 mainmenu.png"); 

Questo renderà lo screenshot dopo un ritardo di 4 secondi.

Dopo l'esecuzione di un'applicazione con la registrazione destra, potrebbe essere stato creato screenshot con i seguenti nomi:

00. SplashScreen.png 
01. MainMenu 01.png 
03. StartLevel 01.png 
04. GameOver 01.png 
05. MainMenu 02.png 

fare un tentativo:

  1. Aggiungere alcune dichiarazioni NSLog al codice

  2. $ tail -f -n0 /var/log/system.log | ./grab.py

  3. crea il tuo iPhone app nel simulatore

  4. giocare con la vostra applicazione

  5. Dai un'occhiata agli screenshots che mostra da dove è stato avviato il programma di grab.py

afferrare.py:

#!/usr/bin/python 

import re 
import os 
from collections import defaultdict 

def screenshot(filename, select_window=False, delay_s=0): 
    flags = [] 
    if select_window: 
     flags.append('-w') 
    if delay_s: 
     flags.append('-T %d' % delay_s) 
    command_line = 'screencapture %s "%s"' % (' '.join(flags), filename) 
    #print command_line 
    os.system(command_line) 

def handle_line(line, count=defaultdict(int)): 
    params = parse_line(line) 
    if params: 
     filebase, fileextension, once, delay_s = params 
     if once and count[filebase] == 1: 
      print 'Skipping taking %s screenshot, already done once' % filebase 
     else: 
      count[filebase] += 1 
      number = count[filebase] 
      count[None] += 1 
      global_count = count[None] 
      file_count_string = (' %02d' % number) if not once else '' 

      filename = '%02d. %s%s.%s' % (global_count, filebase, file_count_string, fileextension) 
      print 'Taking screenshot: %s%s' % (filename, '' if delay_s == 0 else (' in %d seconds' % delay_s)) 
      screenshot(filename, select_window=False, delay_s=delay_s) 

def parse_line(line): 
    expression = r'.*screenshot\s*(?P<once>-once)?\s*(-delay\s*(?P<delay_s>\d+))?\s*(?P<filebase>\w+)?.?(?P<fileextension>\w+)?' 
    m = re.match(expression, line) 
    if m: 
     params = m.groupdict() 
     #print params 
     filebase = params['filebase'] or 'screenshot' 
     fileextension = params['fileextension'] or 'png' 
     once = params['once'] is not None 
     delay_s = int(params['delay_s'] or 0) 
     return filebase, fileextension, once, delay_s 
    else: 
     #print 'Ignore: %s' % line 
     return None 

def main(): 
    try: 
     while True: 
      handle_line(raw_input()) 
    except (EOFError, KeyboardInterrupt): 
     pass 

if __name__ == '__main__': 
    main() 

Problemi con questa versione:

Se si vuole prendere uno screenshot solo la finestra iPhone Simulator, è necessario fare clic sulla finestra iPhone Simulator per ogni screenshot. screencapture si rifiuta di catturare finestre singole a meno che tu non voglia interagire con esso, una strana decisione di progettazione per uno strumento da riga di comando.

Aggiornamento: Ora il cronometro di iPhone simulatore (allo http://www.curioustimes.de/iphonesimulatorcropper/index.html) funziona dalla riga di comando. Quindi, invece di usare la screencapture incorporata, scaricala e usala invece. Quindi ora il processo è completamente automatico.

+2

Uno dei principali problemi con questa tecnica è che richiede uno schermo di hires per funzionare. Realizzo il mio sviluppo su un MBP da 15 "senza un monitor esterno e questo strumento non è in grado di acquisire schermate di dimensioni iPad.Qualsiasi consiglio su come automatizzarlo senza uno schermo più grande? – radven

7

All'interno del iPhone Simulator, v'è una voce di menu "Copia Schermo". Sostituisce la voce di menu Copia nel menu di modifica quando si tiene premuto il tasto Controllo. Il tasto è Ctrl-Cmd-C Un semplice AppleScript può copiare uno ScreenShot e salvarlo. Qualcosa di simile (ha funzionato per me, anche se è hacky):

tell application "iPhone Simulator" to activate 
tell application "System Events" 
    keystroke "c" using {command down, control down} 
end tell 
tell application "Preview" to activate 
tell application "System Events" 
    keystroke "n" using {command down} 
    keystroke "w" using {command down} 
    delay 1 
    keystroke return 
    delay 1 
    keystroke "File Name" 
    keystroke return 
end tell 

Se non si ottiene, si prega di commento ...

0

Si potrebbe anche usare un po 'la schermata di cattura applicazione cattura un video sullo schermo del simulatore.

Io uso molto l'app Jing.

ho anche lo uso per inviare un video che presenta l'applicazione per i clienti ...