czwartek, 31 października 2013

Konformizm w Poker Planningu

Wiesz może dlaczego rozgrywka w Poker Planningu jest tylko jeden raz??

Pięć osób gra w poker planning i estymują jak długo zajmie jedno zadanie.
W pewnym momencie wszystkie osoby pokazują swoje wyniki:

Pierwsza osoba - 8 godzin
Druga osoba - 5 godzin
Trzecia osoba - 8 godzin
Czwarta osoba - 5 godzin
Piąta osoba - 1 godzina


Ale, postanowili jeszcze raz zagrać.

Pierwsza osoba - 8 godzin
Druga osoba - 5 godzin
Trzecia osoba - 8 godzin
Czwarta osoba - 5 godzin
Piąta osoba - 5 godzin


Co się stało z estymatą piątej osoby??

To zjawisko dobrze przestawia eksperyment Solomona Ascha. W eksperymencie Ascha brali udział wolontariusze, którzy na samym początku musieli przyjrzeć się trzem liniom (A,B,C) o rożnej długości, a następnie mieli zdecydować, do której z tych lin najbardziej jest podobna linia czwarta. Linia czwarta była podobna do lini C i z tym stwierdzeniem nie było wątpliwości, jeżeli badani uczestnicy siedzieli sami.



Odpowiedz osób badanych się zmieniła, gdy ten sam przykład był przedstawiony 7 osobom w tym samym czasie. Tak na prawdę w tym eksperymencie było 6 osób podstawionych. Zawsze badana osoba odpowiadała na końcu. Założenie był takie: osoba badana nie zna osób podstawionych. 2 razy podstawione osoby odpowiedzieli poprawnie, ale za 3cim razem odpowiedzieli z błędem. W takiej sytuacji większość osób badanych podążyło za błędną odpowiedzią przedmówców i tak samo odpowiedzieli jak osoby podstawione.

Osoba badana podporządkowała się zdaniu grupy, przy braku nacisku z jej strony. Aschon przedstawił to badanie jako objaw uległości wobec większości - konformizm.

niedziela, 27 października 2013

Korniszonek w BDD

Wymagania szczegółowe aplikacji można zapisać w języku Gherkin. Język ten składa się z 5 słów kluczowych (Given, When, Then, And, But).
Poniżej jest przykład użycia tego języka:

Scenario 1: Zwrot zepsutych butów do magazynu w sklepie
GIVEN: klient kupił buty z naszego sklepu
AND: buty przepuszczają wodę w deszczowe dni
BUT: data zakupu nie starsza niż rok
WHEN: klient zwraca buty,
THEN: buty powinny być w magazynie


Scenario 2: Zakup pasty do butów o 50% taniej przy zakupie butów
GIVEN: klient kupił buty
WHEN: klient chce kupić pastę do butów
THEN: cena pasty do butów o 50% taniej


Są to proste przykłady zastosowania języka Gherkin, które przedstawiają różne zachowania aplikacji.
Więcej można poczytać w książce The Cucumber Book: Behaviour-Driven Development for Testers and Developers oraz na stronie jednego z projektów BDD dla języka php.

W tematyce BDD i Gherkin jestem świeżakiem, ale uważam, że warto zainteresować się tym językiem, gdyż nie wymaga umiejętności programistycznych ze strony testera, PM czy BA, aby napisać przypadek użycia. Książkę jeszcze nie przeczytałem, ale w wolnej chwili muszę się zabrać za nią :)

80% i nie mniej

Przeczytałem świetny tekst o testowaniu na stronie Alberto Savoia (Artima Developera) i uważam, że kwestia pokrycia kodu wciąż powraca, więc zamieszczę spolszczoną wersje Mądrości Testvusa o pokryciu.



Pewnego ranka, młody programista rozmawiał z wielkim mistrzem.
"Jestem gotowy pisać testy jednostkowe. Do jakiego pokrycia kodu powinienem dążyć"
Wielki mistrz odpowiedział:
"Nie przejmuj się pokryciem, po prostu pisz dobre testy"
Młody programista uśmiechnął się, podziękował i poszedł.


Później, tego samego dnia, inny programista zadał to samo pytanie.
Wielki mistrz wskazał na garnek wrzącej wody i powiedział.
"Ile ziarenek ryżu powinienem włożyć do garnka?"
Programista spojrzał zdziwiony i odpowiedział:
"Skąd mogę wiedzieć? To zależy ile ludzi chcesz nakarmić, jak bardzo są głodni, jakie inne jedzenie podajesz, ile masz dostępnego ryżu i tak dalej"
"Dokładnie" - odpowiedział wielki mistrz
Drugi programista uśmiechnął się, podziękował i poszedł.


Pod koniec dnia, trzeci programista przyszedł i zadał to samo pytanie odnośnie pokrycia kodu.
"Osiemdziesiąt procent i nie mniej" - odpowiedział mistrz surowym głosem uderzając ręką o stół
Trzeci programista uśmiechnął się, podziękował i poszedł.


Po ostatniej odpowiedzi, młody uczeń podszedł pod wielkiego mistrza.
"Wielki mistrzu, dzisiaj słyszałem różne Twoje odpowiedzi do tego samego pytania o pokryciu kodu. Dlaczego?"
Wielki mistrz wstał z krzesła.
"Choć napij się ze mną świeżej herbaty i porozmawiajmy o tym"


Po tym jak zaparzyli zieloną herbatę - wielki mistrz zaczął:
"Pierwszy programista jest nowy i dopiero zaczyna znajomość z testowaniem. Teraz ma dużo kodu, który nie ma testów. Długą drogę ma do przebycia, a koncentrując się w tej chwili na pokryciu kodu byłoby przygnębiające i bezużyteczne. Lepiej jest dla niego by przyzwyczaił się do pisania kodu i testów. Później będzie się martwił o pokrycie kodu"


"Drugi programista jest doświadczony w programowaniu i testowaniu. Kiedy odpowiedziałem pytająco, 'ile ziarenek ryżu powinno się umieścić w garnku', to pomogłem mu zrozumieć, że ilość wymaganych testów jest uzależnione od wielu czynników, a on wie lepiej niż ja - bo to jest jego kod. Nie mam jednej prostej odpowiedzi i on jest wystarczająco bystry, aby o tym nie wiedział".


Rozumiem - odpowiedział młody uczeń - ale skoro tam nie ma pojedynczej odpowiedzi, to dlaczego odpowiedziałeś trzeciemu programiście 'Osiemdziesiąt procent i nie mniej'?
Wielki mistrz zaczął się śmiać tak mocno i głośno, że było widać, że wypił coś więcej niż zieloną herbatę.
"Trzeci programista chciał tylko prostych odpowiedzi - nawet, gdyby nie było prostych odpowiedzi, a i tak nie będzie ich przestrzegał"
Młody uczeń i siwy wielki mistrz skończyli pić herbatę w kontemplacyjnej ciszy.


Inne mądrości Testvusa można poczytać na stronie artima lub w wersji pdf.

sobota, 26 października 2013

Statyczne analizy kodu w czasie

Tak się zastanawiam, co by było gdybyśmy wiedzieli jak z biegiem czasu zmieniały się nazwy klas, metod, słowa-klucze używane w naszych projektach. Co jakiś czas kod źródłowy byłby skanowany i informacje byłyby zapisywane do bazy. Z tego można by było przedstawić jaka klasa z biegiem czasu/releasów jest najbardziej popularna, czy nazwy obiektów są zależne od nazwy klas, ile jest komentarzy, jakie jest kodowanie tekstów itp. Mamy narzędzia, aby dokonać statycznej analizy kodu, ale jeszcze nie ma możliwości analizy tych wyników dla okresów czasowych.

Taki pomysł przyszedł mi do głowy przy oglądaniu prezentacji o n-gram. Bardzo zapraszam do obejrzenia:



piątek, 25 października 2013

Testowanie po IEquatable

Tak się zastanawiam nad testowaniem obiektów, które można przyrównać do obiektów tego samego typu (metoda Equals). Przypuśćmy, że masz klasę, która implementuję IEquatable<WrappedString>.
public class WrappedString : IEquatable<WrappedString>
{
        public string StringValue { get; set; }
 
        public WrappedString(string stringValue)
        {
            StringValue = stringValue;
        }
 
        public bool Equals(WrappedString other)
        {
            return this.StringValue == other.StringValue;
        }
}
Każda klasa implementująca IEquatable<WrappedString> powinna spełniać parę standardów, m.in. jeżeli T jest strukturą to domyślna wartość powinna zwrócić tą samą wartość, a kiedy obiekt klasy porównujemy do null zawsze powinna zwracać fałsz.
 public abstract class EquatableRelation<TType> 
        where TType : IEquatable<TType>
{
        public abstract TType GetItemX();  //object to test
        private bool IsValueType()
        {
            return typeof (TType).IsValueType;
        }

  #region Default values
        protected virtual void It_should_return_false_because_comparing_to_null()
        {
            if (!IsValueType())
            {
                TType number1 = GetItemX();
                Assert.IsFalse(number1.Equals(null));
            }
        }
 
        protected virtual void It_should_return_true_for_default_value_in_valueType()
        {
            if (IsValueType())
            {
                var value1 = default(TType);
                var value2 = default(TType);
                Assert.IsTrue(value1.Equals(value2));
            }
        }
        #endregion
}

Obiekt powinien spełniać warunki relacji równoważności.
 public abstract class EquatableRelation<TType> 
        where TType : IEquatable<TType>
{
public abstract TType GetItemX();
public abstract TType GetItemY();
public abstract TType GetItemZ();

#region relation
//relacja zwrotna
protected virtual void It_should_be_reflexive_relation()
{
            TType number1 = GetItemX();
            if (!IsValueType())
            {
                Assert.IsNotNull(number1);
            }
            Assert.IsTrue(number1.Equals(number1));
}

 //relacja symetryczna
protected virtual void It_should_be_symmetric_relation()
{
            TType number1 = GetItemX();
            TType number2 = GetItemY();
 
            bool number1To2 = number1.Equals(number2);
            bool number2To1 = number2.Equals(number1);
            Assert.AreEqual(number1To2, number2To1);
}

//relacja przechodnia
protected virtual void It_should_be_Transitive_relation()
{
            TType number1 = GetItemX();
            TType number2 = GetItemY();
            TType number3 = GetItemZ();
 
            Assert.IsTrue(number1.Equals(number2));
            Assert.IsTrue(number2.Equals(number3));
            Assert.IsTrue(number1.Equals(number3));
 
}
#endregion
}
Oprócz tego zawsze powinno się zwracać taką samą wartość porównania:
 public abstract class EquatableRelation<TType> 
        where TType : IEquatable<TType>
{
private const int NumberOfRepeatedTestRuns = 10;

protected virtual void It_should_return_always_the_same_value_for_Equals()
{
            var bools= new List<bool>();
            for (int i = 0; i < NumberOfRepeatedTestRuns; i++)
            {
                TType number1 = GetItemX();
                TType number2 = GetItemY();
                bools.Add(number1.Equals(number2));
            }
            Assert.IsTrue(bools.All(x => x));
}
 
protected virtual void It_should_return_always_the_same_value_for_reflexive()
{
            var bools= new List<bool>();
            for (int i = 0; i < NumberOfRepeatedTestRuns; i++)
            {
                TType number1 = GetItemX();
                TType number2 = GetItemX();
                bools.Add(number1.Equals(number2));
            }
            Assert.IsTrue(bools.All(x => x));
}

protected virtual void It_should_return_always_true_for_default_values_in_valueType()
{
            if (IsValueType())
            {
                for (int i = 0; i < NumberOfRepeatedTestRuns; i++)
                {
                    var value1 = default(TType);
                    var value2 = default(TType);
                    Assert.IsTrue(value1.Equals(value2));
                }
            }
}
}
Oraz w różnym czasie domyślna wartość powinna zwracać tą samą wartość
 public abstract class EquatableRelation<TType> 
        where TType : IEquatable<TType>
{
 protected virtual void It_should_return_always_the_same_value_for_default_value_in_valueType_for_diffrent_timeTics() //super długa nazwa
{
            if (IsValueType())
            {
                Random r= new Random(12345);
                var defaultvalues = new List<TType>();
                for (int i = 0; i < NumberOfRepeatedTestRuns; i++)
                {
                    Thread.Sleep(r.Next(100,500));
                    defaultvalues.Add(default(TType));
                }
                Assert.IsTrue(defaultvalues.All(x => x.Equals(default(TType))));
            }
        }
}
Ok, to teraz masz standardy jakie powinien spełniać każdy obiekt implementujący IEquatable<WrappedString>. Możemy do tego stworzyć interfejs z tym standardem.
public interface IStandardEquatable
{
  void It_should_fulfill_IEquatable_standards();
}

 public abstract class EquatableRelation<TType>  :IStandardEquatable
        where TType : IEquatable<TType>
{
 public virtual void It_should_fulfill_IEquatable_standards()
{
            It_should_return_true_for_default_value_in_valueType();
            It_should_return_false_because_comparing_to_null();
            It_should_be_reflexive_relation();
            It_should_return_always_the_same_value_for_reflexive();
            It_should_be_coreflexive_relation_because_same_value();
            It_should_return_always_the_same_value_for_Equals();
            It_should_be_symmetric_relation();
            It_should_be_Transitive_relation();
            It_should_return_always_the_same_value_for_default_value_in_valueType();
            It_should_return_always_true_for_default_values_in_valueType();
            It_should_return_always_the_same_value_for_default_value_in_valueType_for_diffrent_timeTics();
}
}
A nasz pierwszy abstrakcyjny test
 public abstract class EquatableRelationTest<TType>  : EquatableRelation<TType>
        where TType : IEquatable<TType>

{
[Test, Explicit("Run test which are required for standardization")]
public override void It_should_fulfill_IEquatable_standards()
{
            base.It_should_fulfill_IEquatable_standards();
}
}

Jeżeli będziesz chciał przetestować int to możesz:
[TestFixture]
public class IntEquatableTest : EquatableRelationTest<int>
{
        public override  int GetItemX()
        {
            return 1;
        }
 
        public override int GetItemY()
        {
            return 1;
        }
 
        public override int GetItemZ()
        {
            return 1;
        }
}
Tak samo dla WrappedString
[TestFixture]
public class WrappedStringEquatableTest :  EquatableRelationTest<WrappedString>
{
        public override WrappedString GetItemX()
        {
            return new WrappedString("Abc");
        }
 
        public override WrappedString GetItemY()
        {
            return new WrappedString("Abc");
        }
 
        public override WrappedString GetItemZ()
        {
            return new WrappedString("Abc");
        }
}
Można skorzystać z TestCasów
[TestFixture]
public class WrappedStringEquatableTest3
{
        [TestCase("Abc", "Abc", "Abc")]
        [TestCase("Abc ", "abc", "Abc")]
        public void It_should_be_eq(string str1, string str2, string str3)
        {
            IEqStdFulfillable tuple =
                new EquatableRelationTuple(new WrappedString(str1), 
                                                          new WrappedString(str2),
                                                          new WrappedString(str3));
            tuple.It_should_fulfill_IEquatable_standards();
        }
}
Do tych testów pomocna będzie nam Tupla i Checker (2 dodatkowe wrappery).
public class EquatableRelationTuple<T> : Tuple<T, T, T>, IStandardEquatable
        where T : IEquatable<T>
{
        private readonly EquatableRelationChecker<T> checker;
 
        public EquatableRelationTuple(T item1, T item2, T item3)
            : base(item1, item2, item3)
        {
            checker = new EquatableRelationChecker<T>(item1, item2, item3);
        }
 
        public void It_should_fulfill_IEquatable_standards()
        {
            checker.It_should_fulfill_IEquatable_standards();
        }
}

 public class EquatableRelationChecker<T> : EquatableRelation<T>
        where T : IEquatable<T>
{
        private readonly T _vakue1;
        private readonly T _value2;
        private readonly T _value3;
 
        public EquatableRelationChecker(T value1, T value2, T value3)
        {
            _vakue1 = value1;
            _value2 = value2;
            _value3 = value3;
        }
 
        public override T GetItemX()
        {
            return _vakue1;
        }
 
        public override T GetItemY()
        {
            return _value2;
        }
 
        public override T GetItemZ()
        {
            return _value3;
        }
}


poniedziałek, 21 października 2013

Problem z statycznymi metodami

Może kiedyś się spotkałeś z klasą, która posiadała dwie metoda (jedna statyczna, druga instancyjna) o jednakowej nazwie,ale innych parametrach i wywołanie nie działało tak jak byś się tego spodziewał. Dla zwyczajnej klasy mamy metodę, która przyjmuje object jako parametr.
public class StaticTestClass
{
        public void Do(object str)
        {
            Console.WriteLine("instance: Do");
        }
}

A wywołanie tej metody działa normalnie:
public void Test()
{
  StaticTestClass abc= new StaticTestClass();
  abc.Do("ASD"); 
}

Jeżeli byśmy mieli dodatkową metodę statyczną, która przyjmuje dokładniejszy typ:
public class StaticTestClass
{
   public static void Do(string str)
   {
      Console.WriteLine("static: StaticTestClass.Do");
   }

   public void Do(object str)
   {
      Console.WriteLine("instance: Do");
   }
}

To mamy wtedy błąd kompilacji
public void Test()
{
  StaticTestClass abc= new StaticTestClass();
  abc.Do("ASD"); //cannot be accessed with an instance reference
}



Kolekcja danych testowych

Jakiś czas temu pisałem o TestCase w NUnit. Czasami takie rozwiązanie może zaoszczędzić troszkę czasu. Zauważyłem, że bardzo często testuje metody dla takich samych danych wejściowych. Dla parametru typu string sprawdzam jak metoda zadziała dla null, pustego stringa i stringa z białym znakiem.
public class SimpleTestClass
{
    [TestCase(null)]
    [TestCase("")]
    [TestCase(" ")]
    public void SimpleTestCase(string parametr)
    {
        Assert.IsTrue(string.IsNullOrWhiteSpace(parametr));
    }
}

A gdyby tak trzymać kolekcję przypadków testowych w oddzielnym miejscu? Mamy taką możliwość - możemy użyć TestCaseSource. Niestety wszystkie metody muszą być statyczne.
[TestCaseSource(typeof(StringTestCaseSource), "NullAndWhiteSpaceStrings")]
public void It_should_return_true(string arg1)
{
   Assert.IsTrue(string.IsNullOrWhiteSpace(arg1));
}

Implementacja metody, która zwraca nam potrzebne dane testowe:
public static class StringTestCaseSource
{
public static IEnumerable<TestCaseData> NullAndWhiteSpaceStrings
{
   get
   {
     yield return new TestCaseData(null);
     yield return new TestCaseData("");
     yield return new TestCaseData(" ");
   }
}
}

Inny przypadek użycia - wartości enumów. Chcielibyśmy uruchomić test dla wszystkich przypadków enuma. Możemy podawać nazwy elementów w enumie jak i jego wartości. Dla enuma:
public enum MoneyDirection
{
        Pay,
        Receive,
}

Możemy napisać proste testy:
[TestCaseSource(typeof(EnumTestCaseSource<MoneyDirection>), "Names")]
public void It_should_parse_moneyDirection_string(string nameOfEnums)
{
           var objectEnum = Enum.Parse(typeof (MoneyDirection), nameOfEnums);
           Assert.IsNotNull(objectEnum);
}
 
[TestCaseSource(typeof(EnumTestCaseSource<MoneyDirection>), "Values")]
public void It_should_parse_moneyDirection_type(MoneyDirection valuesOfEnums)
{
           Assert.IsTrue(Enum.IsDefined(typeof(MoneyDirection), valuesOfEnums));
}
A sama implementacja metod jest następująca:
public static IEnumerable<TestCaseData> Names
{
    get
    {
                return Enum.GetNames(typeof(T))
                       .Select(x => new TestCaseData(x));
    }
}
public static IEnumerable<TestCaseData> Values
{
   get
   {
                return Enum.GetValues(typeof(T))
                      .Cast<T>()
                      .ToTestCaseData(); //with extension method
   }
}

Przypuśćmy, że mamy klasę, która zawiera statyczne formaty dat:
public class DateTimeRequiredFormats
{
        public const string Req1 = "yyyyMMdd"; //const is 
        public readonly static string Req2 = "yyyy  MM  dd";
        public static string Req3 = "yyyy MM dd";
        public string Req4 = ""; //not used because not static
        
        
        ////////////
        public string Req5 { get { return "a"; } }
        public string Req6 { get; set; }
 
        public DateTimeRequiredFormats(string req6)
        {
            Req6 = req6;
        }
 
}

Aby sprawdzić działanie statycznych formatów (Req1, Req2, Req3) wystarczyło wywołać:
[TestCaseSource(typeof(FieldTestCaseSource<DateTimeRequiredFormats>), "Static")]
public void It_should_parse_dateTimeFormat(object arg1)
{
   var dateTime = DateTime.ParseExact("20131029", arg1.ToString(), null,
               DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AllowInnerWhite );
   Assert.AreEqual(new DateTime(2013,10,29), dateTime);
}

A metoda, która zwraca te zmienne ma implementację:
public static class FieldTestCaseSource<T>
{
   public static IEnumerable<TestCaseData> Static
   {
      get
      {
         var propertyInfos = typeof(T).GetFields()
                    .Where(x=>x.IsStatic)
                    .Select(x=>x.GetValue(null))
                    ;
         return propertyInfos.ToTestCaseData();
       }
   }
 }

A co z metoda? Tutaj już jest troszkę trudniejsza sytuacja. Oprócz klasy z metodami to potrzebny będzie nam obiekt, który będzie mógł uruchomić metodę. Poniżej klasa z metodami do uruchamiania w teście:
public class InformationGetter
{
   public static int GetSuperNumber()
   {
     return 77;
   }
 
   public static int GetNotSuperNumber()
   {
      return 7;
   }
 
   public string GetCharAt(int indexNumber)
   {
      return _specialString[indexNumber]
.ToString(CultureInfo.InvariantCulture);
   }
   private string _specialString;
 
   public InformationGetter(string specialString)
   {
     _specialString = specialString;
   }
 
   public void ConsoleWrite()
   {
      Console.WriteLine("ConsoleWirte:" + _specialString);
   }
}
Poniżej sam test. Zauważ, że podany tej tutaj typ zwracany przez metodę (int).
[TestCaseSource(typeof(MethodTestCaseSource<InformationGetter,int>), "Static")]
public void It_should_return_int_bigger_than_0(MethodInvoker<int> staticMethodToInvoke)
{
   Assert.Greater(staticMethodToInvoke.Invoke(), 1);
}
public static class MethodTestCaseSource<T, TReturn>
{
   public static IEnumerable<TestCaseData> Static
   {
     get
     {
       var methodInfos=  MethodTestCaseSource<T>.GetStaticMethods()
                    .Where(x => x.ReturnType == typeof (TReturn));
       var methodInvokers = MethodInvoker<TReturn>.ToInvoker(methodInfos);
       return methodInvokers
                    .ToTestCaseData(x=>x.Method.Name);
      }
   }
   public static IEnumerable<TestCaseData> NonStatic
   {
      get
      {
        var methods = MethodTestCaseSource<T>.GetInstanceMethods()
                    .Where(x => x.ReturnType == typeof(T));
 
        var methodInvokers = MethodInvoker.ToInvoker(methods);
        return methodInvokers
                    .ToTestCaseData(x => x.Method.Name);
       }
   }
}
Klasa MethodInvoker wywołuje daną metodę. Klasa ma dwie postacie (bez i z użyciem generyków). Jedna i druga metoda ma podobną implementację.
public class MethodInvoker<TReturn> : MethodInvoker
{
   public MethodInvoker(MethodInfo methodInfo):base(methodInfo){}
 
   public TReturn Invoke(object obj=null, object[] parameters=null)
   {
     return (TReturn)Method.Invoke(obj, parameters);
   }
 
   public static IEnumerable<MethodInvoker<TReturn>> ToInvoker(IEnumerable<MethodInfo> methodInfos)
   {
     return methodInfos.Select(x => new MethodInvoker<TReturn>(x));
   }
}
Dzięki MethodInvoker możemy też przesyłać metody, które nie są statyczne. Wystarczy dla metody Invoke podać obiekt:
[TestCaseSource(typeof(MethodTestCaseSource<InformationGetter, string>), "NonStatic")]
public void It_should_return_first_char(MethodInvoker<string> nonStaticMethodToInvoke)
{
  InformationGetter getter=new InformationGetter("Abc");
  var fistCharString = nonStaticMethodToInvoke.Invoke(getter, new object[] {0});
  StringAssert.AreEqualIgnoringCase("a", fistCharString);
}

Kod źródłowy projektu jest udostępniony na GitHubie. Coś może dodam do tych kolekcji testcesów np. wygenerowane losowe stringi, dane z plików resx, najważniejsze daty w DateTime, adresy url i mail.
Możesz też zainstalować sobie paczkę nugetową. Wystarczy wpisać:
>Install-Package Nunit.Framework.TestCaseStorage



niedziela, 20 października 2013

Fluent notation

Osoby, które kodują razem ze mną to od razu wiedzą, że jestem autorem danej części kodu. Pisany kod jest w stylu Fluent notation ( również zwany Fluent interface, gdyż przygotowujesz całe API). Co prawda wielu osobom się to nie podoba, ale chciałbym Ci przedstawić mój sposób widzenia:

Zapis LINQ w tradycyjny jednolinijkowy sposób pisania kod:
var firstNumberSelector = GetNumbers().Where(x => x > 0).
    ToLookup(x => x.ToString().First()).Select(x => new{x.Key, Items = x,Count = x.Distinct().Count()}).ToList();

A tutaj mój sposób pisania kodu:
var firstNumberSelector = GetNumbers()
                .Where(x => x > 0)
                .ToLookup(x => x.ToString()
                                .First())
                .Select(x=>new {x.Key, 
                                Items=x, 
                                Count=x.Distinct()
                                        .Count()})
                .ToList();
Projekt Fluent NHibernate korzysta z takiego zapisu i kod może wyglądać tak:
_SessionFactory = Fluently 
                .Configure() 
                .Database(MsSqlCeConfiguration 
                              .Standard 
                              .ConnectionString("Data Source=MyDb.sdf") 
                              .ShowSql()
                               )
                .Mappings(m => m.FluentMappings 
                           .AddFromAssemblyOf<NHibernateHelper>()) 
                .ExposeConfiguration(cfg => new SchemaExport(cfg) 
                                        .Create(true, true)   //create table in db 
                                        ) 
                .Cache(c=>c 
                    .UseSecondLevelCache() 
                    .UseQueryCache() 
                    .ProviderClass<HashtableCacheProvider>() 
                    ) 
                .BuildSessionFactory();
Dla mnie jest to kod bardziej czytelny i łatwiej mi jest określić jaka metoda jest uruchamiana dla danego obiektu.
Może Tobie też spodoba się taki sposób pisania kodu.

środa, 16 października 2013

Kolorowanie składni w Visual Studio

Edytor środowiska programistycznego (IDE) jest narzędziem, przy którym programista spędza 99% swojego czasu. Nie będę Ci mówił, że kolorowa składnia jest bardzo ważna. Celem tego wpisu jest przesłanie Ci ciekawych rozwiązań zestawu kolorów.

Już dawno temu Atwood, Hanselman czy Restrepo pisali o kolorowaniu środowiska programistycznego.

Na stronie Studio Style można pobrać style do edytora Visual Studio. Oprócz tego sam możesz stworzyć własny styl dopasowany do Twojego gustu. Oczywiście w każdym momencie można wrócić do domyślnego stylu.

Dla Visual Studio 2013 (i innych wersji od VS2010) jest jeszcze dodatek Color Theme Editor, który zmieniasz menu VS.

niedziela, 13 października 2013

Jestem OK ponieważ

Czy Ty jesteś OK
Zrób takie małe ćwiczenia. Zapisz 4 zdania określające Ciebie, czy jesteś w porządku. Np.
Jestem OK, dopóki pomagam innym
Jestem OK, bo mam luksusowy dom
Jestem OK, ponieważ noszę markowe ubranie
Jestem OK, gdyż jestem poważany

Teraz napisz 4 zdania określające ciebie.
Napisz teraz.





Z pewnej książki zapoznałem się z metodyką "Jestem Ok, ponieważ ..."
Jest to metoda, która uświadomiła mnie jakie mam lęki, dlaczego moje wartości są kruchliwe oraz wzmocniła moje poczucie własnej wartości.

Jest to metoda, która określa Twój szacunek do samego siebie. Na przykład, jeśli rodzice chwalili cię wtedy kiedy zdobywałeś dobre oceny w szkole to mówiłeś do siebie "jestem OK, dopóki mam dobre oceny". Z biegiem lat mogłeś rozwinąć warunkowe poczucie własnej wartości i jeżeli nic nowego się nie zdarzyło, to taka "wartość" towarzyszyła Ci przez okres dojrzałości prowadzać do rozczarowań oraz wątpliwości we własne możliwości, kiedy nie będzie odnosiło się sukcesów.
Warunkowa wartość jest rozwijana wewnątrz nas. Problem powstaje, kiedy takiego warunku nie jesteśmy w stanie spełnić, co będzie prowadziło do poczucia niskiej wartości. Zamiast takiej wartości można zadać sobie wartość Jestem OK, niezależnie od tego czy odnoszę sukces.

Inne warunki określające naszą wartość to:
Jestem OK, ponieważ uczę się
Jestem OK, ponieważ wygrywam
Jestem OK, ponieważ jestem wolontariuszem
Jestem OK, ponieważ ciężko pracuję
Jestem OK, ponieważ znam się na kinie
Jestem Ok, bo dużo zarabiam
Jestem OK, dopóki mam co robić
Jestem OK, dopóki mam wiele przyjaciółek
Jestem OK, dopóki jestem dla kogoś ważny/-na
Jestem OK, dopóki pomagam innym
Jestem OK, bo jadam w drogich restauracjach
Jestem OK, bo jestem z moim partnerem/-ką
Jestem OK, bo jestem uczciwy
Jestem OK, bo kontroluje innych
Jestem OK, bo chodzę w modnym ubraniu
Jestem OK, bo chodzę na siłownię
Jestem OK, bo wiem co jest smaczne
Jestem OK, bo znam się na nowościach technologicznych




Przez warunkową wartość możemy robić coś, co nie daje nam satysfakcji. Dążenie do celu nie jest z powodu chęci (motywacja pozytywna), ale z powodu strachu (motywacja negatywna). Dochodzi do tego, że można wykonać cele wbrew naszym wewnętrznym wartościom. Sprawdź czy Twoje cele są zgodne z Twoimi wartościami.

piątek, 11 października 2013

Microsoft Security Fundamentals

Ostatnio zdałem egzamin MTA:Security Fundamentals 98-367

Z dwóch powodów polecam ten egzamin osobom pracującym w firmach, które dbają o bezpieczeństwo (instytucje finansowe, banki, ubezpieczenia, firmy medyczne itp.)

1) przygotowanie się do tego egzaminu pozwali Ci na zaznajomienie się z podstawowymi technikami włamywania się do firm, a w szczególności uświadamia ludzi o socjotechnikach
2) egzamin jest nakierowany na teoretyczną i ogólną wiedzę, a nie na szczegóły implementacji. Osoby, które twierdzą, że Microsoft jest 'beee' i nie znają jego produktów mogą zdać ten egzamin. Co prawda pamiętam jedno pytanie z BitLockera (microsoftowy TruCrypt) i o wersje Windows, w której to rozwiązanie jest używane (źle odpowiedziałem), ale było to jedno pytanie.

Jeżeli byś chciał się przygotować do niego to przydatny będzie Ci oficjalny przewodnik po tym egzaminie
Dodatkowo możesz poczytać inne książki z obszaru bezpieczeństwa Windows - na przykład Google books udostępniło książkę Windows Security Essencials.

Obejrzałem jeszcze filmiki na trainsignal.com oraz cbt nuggets.

Wydaje mi się, że książka przygotowująca do egzaminu w zupełności by wystarczała, ale wiedzy nigdy za wiele.

sobota, 5 października 2013

Walka z CSS

Tak się zastanawiam i dochodzę do wniosku, że osoby, które potrafią stworzyć piękne strony za pomocą modyfikacji css'a muszą mieć coś z artysty. Ja (niestety) nie mam takiej umiejętności, a bardzo bym chciał. Może w przyszłości troszkę się pobawię, ale zawsze jak biorę się za selectory, to muszę całą stronę zepsuć.
Rozbawiła mnie znaleziona grafika Petera Griffina jak próbuje ustawić żaluzje i fantastycznie przedstawia moją walkę z CSS.

środa, 2 października 2013

Porównanie C5 z System.Collections.Generic

Jestem po lektorze książki ".NET 4.0 Generics" napisanej przez Sudipta Mukherjee (wcześniej na jego stronie można było ściągnąć całą książkę). Najbardziej cenie tą książkę za przedstawienie wyników szybkości działania różnych typów kolekcji. Autor porównuje typy, które znajdują się w bibliotece C5 oraz w System.Collections.Generic. O bibliotece C5 już wcześniej pisałem. Chciałbym przedstawić zdjęcia z wynikami z tej książki.

Eksperyment nr 1:
Ile czasu potrzeba, aby sprawdzić czy element w liście istnieje.

Eksperyment nr 2:
Ile czasu potrzeba, aby znaleźć pierwsze wystąpienie elementu w liście.


Eksperyment nr 3:
Ile czasu potrzeba, aby znaleźć ostatnio występujący element w liście


Eksperyment nr 4:
Ile czasu potrzeba, aby dodać element w losowym miejscu w liście


Eksperyment nr 5:
Ile czasu potrzeba, aby usunąć pojedynczy element w losowym miejscu w liście


Eksperyment nr 6:
Ile czasu potrzeba, aby uzyskać dostęp do elementu w kolekcji asocjacyjnej (Dictionary, SortedDictionary, C5.HashDictionary, C5.TreeDictionary)


Eksperyment nr 7:
Ile czasu potrzeba, aby znaleźć unie dwóch zbiorów


Eksperyment nr 8:
Ile czasu potrzeba, aby sprawdzić czy jeden zbiór zawiera się w drugim zbiorze


Kod źródłowy dla tych testów można było pobrać stąd. Mam nadzieję, że Sudipta reaktywuje swoją stronę.