2014-12-02 15 views
5

Sto provando a testare un'applicazione Web ASP.NET MVC4 che si connette con diversi utenti allo stesso tempo utilizzando la rappresentazione. Quindi, l'idea per il test era di eseguire diverse istanze del driver ciascuna con un utente diverso impersonato. Sembra concettualmente facile ...IEDriverServer genera un errore durante l'utilizzo della rappresentazione

Tuttavia, se dopo aver chiamato LogonUser con un utente diverso da quello corrente, si esegue IEDriverServer, all'avvio viene visualizzata una finestra di dialogo di errore dell'applicazione. Questa è l'informazione registrata nel EventLog:

Faulting application name: IEDriverServer.exe, version: 2.44.0.0, time stamp: 0x54496690 
Faulting module name: IED7543.tmp, version: 0.0.0.0, time stamp: 0x5449668c 
Exception code: 0xc0000005 
Fault offset: 0x000000000009d609 
Faulting process id: 0x760 
Faulting application start time: 0x01d00e3d12f93475 
Faulting application path: ...\bin\IEDriverServer.exe 
Faulting module path: C:\Users\user\AppData\Local\Temp\IED7543.tmp 
Report Id: 5383a54d-7a30-11e4-b39c-000c29b46927 

Ecco il codice che sto usando per la rappresentazione. Essa si basa in tutti gli esempi che ho trovato, quindi non ci sono sorprese ... Abbiamo anche cercato di utilizzare il SimpleImpersonation packege con lo stesso risultato:

public class ImpersonationHelper 
{ 
    public enum LogonType 
    { 
     Interactive = 2, 
     Network = 3, 
     Batch = 4, 
     Service = 5, 
     Unlock = 7, 
     Cleartext = 8, // Win2K or higher 
     NewCredentials = 9 // Win2K or higher 
    }; 

    public enum LogonProvider 
    { 
     Default = 0, 
     Winnt35 = 1, 
     Winnt40 = 2, 
     Winnt50 = 3 
    }; 

    public enum ImpersonationLevel 
    { 
     SecurityAnonymous = 0, 
     SecurityIdentification = 1, 
     SecurityImpersonation = 2, 
     SecurityDelegation = 3 
    } 

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
    public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, 
     int dwLogonType, int dwLogonProvider, out IntPtr phToken); 

    [DllImport("kernel32.dll")] 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    [SuppressUnmanagedCodeSecurity] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool CloseHandle(IntPtr handle); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public static extern int DuplicateToken(IntPtr hToken, 
     int impersonationLevel, ref IntPtr hNewToken); 

    public sealed class Impersonator : IDisposable 
    { 
     public string Domain { get; private set; } 
     public string User { get; private set; } 
     public string Password { get; private set; } 
     public LogonType Type { get; private set; } 
     public LogonProvider Provider { get; private set; } 

     private WindowsImpersonationContext _context; 
     private IntPtr _token; 

     [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")] 
     public Impersonator(string domain, string user, string password, 
      LogonType type = LogonType.Interactive, 
      LogonProvider provider = LogonProvider.Default) 
     { 
      Domain = domain; 
      User = user; 
      Password = password; 
      Type = type; 
      Provider = provider; 
      _token = IntPtr.Zero; 

      Logon(); 
     } 

     public void Dispose() 
     { 
      Undo(); 
     } 

     private void Logon() 
     { 
      try 
      { 
       if (!LogonUser(User, Domain, Password, (int)Type, (int)Provider, out _token)) 
       { 
        int ret = Marshal.GetLastWin32Error(); 
        throw new Exception(String.Format("LogonUser failed with error code : {0}", ret)); 
       } 

       _context = WindowsIdentity.Impersonate(_token); 
      } 
      catch (Exception exception) 
      { 
       var message = exception.Message; 
       Undo(); 
      } 
     } 

     private void Undo() 
     { 
      try 
      { 
       if (_token != IntPtr.Zero) 
       { 
        CloseHandle(_token); 
        _token = IntPtr.Zero; // Clean _token so Undo() could be called several times 
       } 

       if (_context != null) 
       { 
        _context.Undo(); 
        _context = null; // Clean _context so Undo() could be called several times 
       } 
      } 
      catch (Exception exception) 
      { 
       var message = exception.Message; 
       // Releasing resources failed... 
      } 
     } 
    } 
} 

Il codice che genera l'eccezione è:

using (new ImpersonationHelper.Impersonator("WIN-NKLTTMMUEPD", "tester", "tester")) 
{ 
    using (IWebDriver driver = new InternetExplorerDriver()) 
    { 
     driver.Url = _appAddress; 
     return null; 
    } 
} 

Qualcuno sa come posso evitare che questo errore venga visualizzato? Grazie mille in anticipo.

risposta

2

Non è stato possibile riprodurre l'arresto anomalo di IEDriver.

Tuttavia, come hai messo una taglia su questa domanda, non mi importava passare un po 'di tempo cercando di trovare una soluzione. Non ho mai implementato l'autenticazione di Windows o necessario per verificare la rappresentazione prima, tuttavia ho esperienza con i test di automazione dell'interfaccia utente.

Time-boxed per un'ora:

  • creato un'applicazione di esempio Intranet MVC che utilizza l'autenticazione di Windows;
  • aggiunto un nuovo progetto e impostato un test di unità di base che carica il sito.
  • ha aggiunto la rappresentazione.

Non sono sicuro di come siano stati implementati esattamente i test, tuttavia i progetti .NET/MVC mi consigliano vivamente di utilizzare Seleno. È un involucro attorno al Selenium Web Driver (che cosa stai usando al momento), tuttavia rende l'UI test meno doloroso/fragile forzando la convenzione di implementare oggetti Page e componenti della pagina e leggere e scrivere dati di pagine web usando modelli di visualizzazione fortemente tipizzati.

Inoltre, si consiglia di utilizzare la libreria SimpleImpersonation in quanto è un'implementazione più sicura/pulita della funzione LogonUser API Win32, ad es. usa SafeHandle e il percorso di smaltimento è più pulito.

Il test che ho scritto,

[Test] 
public void GivenImpersonatedUser_IsLoggedInCorrectly() 
{ 
    const string domain = "domain"; // . for local machine 
    const string username = "impersonate.username"; 
    const string password = "[email protected]"; 

    const LogonType logonType = LogonType.Interactive; 

    using (Impersonation.LogonUser(domain, username, password, logonType)) 
    { 
     var page = Host.Instance.NavigateToInitialPage<HomePage>(); 
     Assert.That(page.LoginPanel.LoggedInUserName, Is.EqualTo(string.Format("{0}\\{1}", domain, username))); 
    } 
} 

Questo è l'oggetto Seleno pagina, chiamato HomePage, che utilizza un componente riutilizzabile LoginPanel.

public class HomePage : Page 
{ 
    public LoginPanel LoginPanel 
    { 
     get { return GetComponent<LoginPanel>(); } 
    } 
} 

public class LoginPanel : UiComponent 
{ 

    public string LoggedInUserName 
    { 
     get { return Find.Element(By.Id("login-username")).Text; } 
    } 
} 

Configurazione Seleno host, utilizzando IEDriver.

public static class Host 
{ 
    private static readonly InternetExplorerDriver Driver = new InternetExplorerDriver(); 

    public static readonly SelenoHost Instance = new SelenoHost(); 

    static Host() 
    { 
     Instance.Run(c => 
     { 
      c.WithRemoteWebDriver(() => Driver); 
      c.ProjectToTest(new WebApplication(ProjectLocation.FromFolder("WebApplication1"), 61285)); 

      c.UsingLoggerFactory(new ConsoleFactory()); 
      c.UsingCamera("C:\\screenshots"); 
     }); 
    } 
     var codeBase = assembly.CodeBase; 
     var uri = new UriBuilder(codeBase); 
     var path = Uri.UnescapeDataString(uri.Path); 

     return Path.GetDirectoryName(path); 
    } 

} 

A poche altre cose che ho imparato: - Si otterrà il codice di errore 1326 se il nome utente o la password sono errati. - È possibile utilizzare Process Hacker per confermare che il processo di webdriver sia avviato con il token di autenticazione corretto.

Come ho già detto, non ero in grado di rispondere al tuo problema esatto, tuttavia prova a utilizzare quanto sopra e commenta - felice di aiutare ulteriormente.

+1

La tua risposta è piena di informazioni preziose per continuare a cercare come eseguire test che coinvolgono diversi utenti. Grazie mille! L'errore, tuttavia, si è rivelato essere un problema riguardante la versione x64 del driver. – yeyeyerman

+0

Mi dispiace che non ho potuto risolvere il tuo problema esatto. – Dennis

Problemi correlati