Magazine

Un Generatore per testare il databinding

Andrea Boschin

29/05/2006

Un breve articolo che spiega come realizzare una classe mock che fornisca dei dati casuali tipizzati per testare il binding di controlli webform e winform

0%100%
per esprimere un voto รจ necessario registrarsi al sito

Reflection

Quando nello sviluppo si una applicazione si procede demandando i diversi livelli dell'architettura a diverse persone nel team può capitare che vi sia un disallineamento tra lo stato di avanzamento del datalayer, quello della businesslogic e il presentation layer. In altri casi è addirittura opportuno poter testare separatamente i diversi layer, ad esempio per ottimizzare le performances della User Interface di fronte ad una mole di dati superiore a quella normalmente disponibile. Per occasioni di questo tipo mi sono creato un generatore casuale di dataentity che è in grado di fornirmi dei dati tipizzati, sotto forma di istanze di oggetti di business, in una forma tale da essere facilmente bindabile all'interfaccia. I dati, che in realtà sono completamente casuali hanno la caratteristica importante di essere generati in un tipo specifico per ogni proprietà dell'oggetto di business. Questo consente di verificaare le reazioni dell'interfaccia ad esempio a range di date molto ampie, a numerici molto piccoli o molto grandi, a diverse precisioni di decimal etc. Ecco la classe che mi sono creato:

public static class Generator
{
    
public static T GenerateRandom<T>()
        where T : 
new()
    {
        T instance = 
new T();

        Type type = 
typeof(T);
        
foreach (PropertyInfo property in type.GetProperties())
            property.SetValue(instance, GetRandomValue(property.PropertyType), 
null);

        
return instance;
    }

    
public static List<T> GenerateRandomList<T>(int elements)
        where T : 
new()
    {
        List<T> list = 
new List<T>();

        
for (int i = 0; i < elements; i++)
            list.Add(Generator.GenerateRandom<T>());

        
return list;
    }
    
    
public static DataTable GenerateRandomDataTable<T>(int elements)
        where T : 
new()
    {
        DataTable table = 
new DataTable();

        PropertyInfo[] properties = 
typeof(T).GetProperties();

        
foreach (PropertyInfo property in properties)
            table.Columns.Add(property.Name, property.PropertyType);

        
for (int i = 0; i < elements; i++)
        {
            DataRow row = table.NewRow();

            T instance = GenerateRandom<T>();

            
foreach (PropertyInfo property in properties)
                
if (property.Name!="Item")
                    row[property.Name] = property.GetValue(instance, 
null);

            table.Rows.Add(row);
        }

        
return table;
    }

    
public static object GetRandomValue(Type type)
    {
        
if (type.Equals(typeof(short)))
            
return GetRandomInt16();
        
else if (type.Equals(typeof(int)))
            
return GetRandomInt32();
        
else if (type.Equals(typeof(long)))
            
return GetRandomInt64();
        
else if (type.Equals(typeof(string)))
            
return GetRandomString();
        
else if (type.Equals(typeof(DateTime)))
            
return GetRandomDateTime();
        
else if (type.Equals(typeof(double)))
            
return GetRandomDouble();
        
else if (type.Equals(typeof(decimal)))
            
return GetRandomDecimal();
        
else if (type.Equals(typeof(bool)))
            
return GetRandomBoolean();
        
else if (type.Equals(typeof(object)))
            
return GetRandomString();

        
return null;
    }

    
private static short GetRandomInt16()
    {
        Random rand = 
new Random(DateTime.Now.Millisecond);
        
return (short)rand.Next(short.MaxValue);
    }

    
private static int GetRandomInt32()
    {
        Random rand = 
new Random(DateTime.Now.Millisecond);
        
return rand.Next(int.MaxValue);
    }

    
private static long GetRandomInt64()
    {
        Random rand = 
new Random(DateTime.Now.Millisecond);
        
return (long)(rand.Next(int.MaxValue) << 32 | rand.Next(int.MaxValue));
    }

    
private static object GetRandomString()
    {
        
return Guid.NewGuid().ToString().Replace('-'' ');
    }

    
private static object GetRandomDateTime()
    {
        
long ticks = GetRandomInt64();
        
return new DateTime(ticks);
    }

    
private static object GetRandomBoolean()
    {
        Random rand = 
new Random(DateTime.Now.Millisecond);
        
return (rand.Next(0, 1)==1);
    }

    
private static object GetRandomDecimal()
    {
        
return (decimal)GetRandomDouble();
    }

    
private static object GetRandomDouble()
    {
        Random rand = 
new Random(DateTime.Now.Millisecond);
        
return rand.NextDouble() * rand.Next(int.MaxValue);
    }
}

La classe è in grado di produrre singoli oggetti del tipo richiesto, oppure liste di oggetti contenenti il numero di elementi richiesto. Per chi ha la necessità di testare il binding a delle DataTable il generatore è in grado di popolare una DataTable sulla base di una classe che funge da template per le proprietà da esporre nella DataTable.

L'uso dei Generics, Rende molto semplice l'uso del Generatore. Dopo aver creato la propria classe sorgente per una ObjectDataSource, molto semplicemente si potrà creare un metodo apposito che restituisca la collection richiesta:

public List<Product> GetTestProducts()
{
    
return Generator.GenerateRandomList<Product>(1000);
}

La classe potrebbe essere facilmente estesa aggiungendo dei meccanismi di cache per evitare che la generazione di un numero elevato di oggetti ad ogni chiamata possa influire negativamente sulle prestazioni del Garbage Collector.

Commenti
  • Molto utile :-)

    di Stefano - 20/10/2006 5.02.44
Nome

Sito web
Commento


indietro