C# 7.0 – Tuples

Klasa (immutable) Tuple istniała aż od .NET Framework 4.0. W C# 7.0 mamy jednak wsparcie dla tuple od strony języka. Jednym z problemów klasy Tuple było, że każda właściwość nazywała się kolejno Item1, Item2 itp.

Przykład:

    class Program
    {
        private static void Main(string[] args)
        {
            var tuple = GetFirstAndLastName();

            Console.WriteLine(tuple.Item1);
            Console.WriteLine(tuple.Item2);
        }

        private static Tuple<string,string> GetFirstAndLastName()
        {
            var tuple = new Tuple<string, string>("Piotr", "Zielinski");

            return tuple;       
        }
    }

W wersji 7.0, powyższy kod możemy przepisać do:

    class Program
    {
        private static void Main(string[] args)
        {
            var tuple = GetFirstAndLastName();

            Console.WriteLine(tuple.firstName);
            Console.WriteLine(tuple.lastName);
        }

        private static (string firstName, string lastName) GetFirstAndLastName()
        {
            var fullName = (firstName: "Piotr", lastName: "Zielinski");

            return fullName;
        }
    }

Składnia dużo czytelniejsza ponieważ nie operujemy już na Item1 i Item2. Zobaczmy co się kryje za tym nowym “Tuple” po dekompilacji:

  internal class Program
  {
    // Method .ctor with token 06000003
    public Program()
    {
      base.\u002Ector();
    }

    // Method Main with token 06000001
    private static void Main(/*Parameter with token 08000001*/string[] args)
    {
      ValueTuple<string, string> firstAndLastName = Program.GetFirstAndLastName();
      Console.WriteLine(firstAndLastName.Item1);
      Console.WriteLine(firstAndLastName.Item2);
    }

    // Method GetFirstAndLastName with token 06000002
    private static ValueTuple<string, string> GetFirstAndLastName()
    {
      return new ValueTuple<string, string>("Piotr", "Zielinski");
    }
  }

Całość opiera się na zwykłej strukturze ValueTuple<string, string>. Wygląda to bardzo analogicznie do starego Tuple<T1,T2>. Zaglądając do źródeł ValueTuple, przekonamy się, że klasa jest immutable i  przeładowuje metody typu Equals oraz GetHashCode. Oznacza to, że typ doskonale nadaję się jako klucz do słowników.

Powyższy kod można przetestować używając Visual Studio ’15’ preview 3,  który jest dostępny tutaj.

ASP.NET Core – wstrzykiwanie zależności

ASP.NET Core ułatwia w znaczący sposób IoC. Przede wszystkim wbudowano w framework dosyć prostą implementację IoC. Oznacza to, że w wielu przypadkach nie trzeba już instalować zewnętrznych framework’ow takich jak AutoFac.  W pliku Startup znajdziemy metodę ConfigureServices:

        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddApplicationInsightsTelemetry(Configuration);

            services.AddMvc();
        }

Jeśli chcemy zarejestrować instancję jako singleton wtedy wystarczy:

services.AddSingleton<ITest, ConcreteTest>();

Nic więcej nie trzeba konfigurować. Instancja automatycznie zostanie wstrzyknięta do kontrolerów jak i widoków. Sprawa w przypadku kontrolerów wygląda prosto i wystarczy po prostu stworzyć konstruktor:

        public HomeController(ITest test)
        {
            _test = test;
        }

W przypadku widoków, również możemy korzystać z wstrzykniętych instancji:

@using Microsoft.Extensions.Configuration
@inject ITest test

@{
    ViewData["Title"] = "About";
}

<h2>@ViewData["Title"].</h2>


<h3>@ViewData["Message"]</h3>




@test.GetText()


AddSingleton tworzy oczywiście pojedynczą instancję. Istnieje również metoda AddTriansient:

services.AddTransient<ITest, ConcreteTest>();

Tworzy ona nową instancję za każdym razem, gdy dochodzi do wstrzyknięcia.

Inny sposób to AddScoped:

services.AddScoped<ITest, ConcreteTest>();

AddScoped będzie współdzielić instancję w ramach tego samego zapytania. Przydatne, kiedy mamy wiele klas do których wstrzykujemy ten sam typ. W wielu przypadkach nie ma potrzeby tworzenia osobnych instancji.

Cykl BDD\TDD

Zarówno o BDD, jak i TDD wiele razy już pisałem. Najważniejszą rzeczą w TDD jest sekwencja red-green-refactor.  Zwykle BDD\TDD przybiera następującą postać:

  1.  Zaczynamy od etapu BDD. Definiujemy wymagania za pomocą języka rozumianego zarówno przez programistów jak i jak BA\PO. Za pomocą Specflow możemy zdefiniować np. następujący test:
        Given I have entered 50 into the calculator
        And I have entered 70 into the calculator
        When I press add
        Then 120 should be displayed on the screen
    
  2. W celu zaimplementowania powyższej specyfikacji, rozpoczynamy cykl TDD. W tym celu tworzymy serie klasycznych testów jednostkowych. Cykl TDD trwa do momentu, kiedy specyfikacja z punktu pierwszego zostanie zaimplementowana.
  3. Definiujemy następną specyfikację, rozpoczynając zatem kolejny cykl TDD.

Innymi słowy, na każdą specyfikacje BDD, przypada ileś testów TDD. Wszystko jest wykonywane na zasadzie red-green-refactor. Definiując specyfikację BDD w punkcie pierwszym, oczywiście taki test będzie czerwony dopóki nie przeprowadzimy cyklu TDD.

Testy UI: Wzorzec PageObject

O testach UI, szczególnie w SpecFlow pisałem już kilka razy. Zawsze korzystałem z wzorca PageObject, chociaż nie wiedziałem, że ma on swoją nazwę. Czasami mam wrażenie, że na proste rzeczy wymyśla się “wzorce”. Muszę przyznać jednak, że  uproszcza to często komunikację między programistami. Wzorce w końcu stanowią pewnego rodzaju słownictwo dla programistów. Zamiast opisywać coś w kilku zdaniach, można powiedzieć po prostu nazwę wzorca.

PageObject pattern polega na tym, że pisząc testy jednostkowe, opakowujemy stronę w obiekty C#.  Początkujący programiści często piszą testy  w stylu:

        [Test]
        public void Query_ShouldBe_Persisted_When_SearchButtonIsClicked()
        {
            IWebDriver driver = new ChromeDriver();
            driver.Navigate().GoToUrl("http://www.bing.com");

            var textBox = driver.FindElement(By.Id("sb_form_q"));
            textBox.SendKeys("piotr zielinski c#");

            var searchButton = driver.FindElement(By.Id("sb_form_go"));
            searchButton.Click();

            string query = driver.FindElement(By.Id("sb_form_q")).GetAttribute("value");
            Assert.That(query,Is.EqualTo("piotr zielinski c#"));
        }

Test jest trudny w zrozumieniu oraz czasochłonny w utrzymaniu. Idealny test powinien być czytany jak skrypt opisujący kolejne akcje. W PageObject opakowujemy strony w obiekty c#. W naszym przypadku stworzymy dwa obiekty, SearchForm oraz SearchResults:

   public class SearchForm
    {
        private readonly IWebDriver _webDriver;

        public SearchForm(IWebDriver webDriver)
        {
            _webDriver = webDriver;
        }

        public SearchResults Search(string query)
        {
            var textBox = _webDriver.FindElement(By.Id("sb_form_q"));
            textBox.SendKeys(query);

            var searchButton = _webDriver.FindElement(By.Id("sb_form_go"));
            searchButton.Click();

            return new SearchResults(_webDriver);
        }        
    }
    public class SearchResults
    {
        private readonly IWebDriver _webDriver;

        public SearchResults(IWebDriver webDriver)
        {
            this._webDriver = webDriver;
        }

        public string GetQuery()
        {
            return _webDriver.FindElement(By.Id("sb_form_q")).GetAttribute("value");
        }
    }

Test zatem wygląda teraz następująco:

            IWebDriver driver = new ChromeDriver();
            driver.Navigate().GoToUrl("http://www.bing.com");
            const string query = "Piotr zielinski c#";
          
            var searchForm=new SearchForm(driver);
            var searchResults = searchForm.Search(query);

            Assert.That(searchResults.GetQuery(), Is.EqualTo(query));

Zwykle opakowuję również sterownik czyli interfejs IWebDriver. Można stworzyć obiekt o nazwie np. BingWebsite który będzie stanowił bramkę do wszelkich testów. Celem jest, aby jakikolwiek kod Selenium nie znajdował się bezpośrednio w teście. Dzięki temu, ten sam kod może być wykorzystywany w różnych testach. Ponadto, przy skomplikowanych testach, kod jest dużo prostszy w rozumieniu ponieważ stanowi skrypt bez magicznych zmiennych.

tSQLt – testowanie wyzwalaczy

O tSQLt pisałem już wiele razy. Dzisiaj chciałbym pokazać jak testować wyzwalacze (triggers). Załóżmy, że mamy następującą tabelę:


CREATE TABLE [dbo].[Articles](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[Price] [int] NULL,
 CONSTRAINT [PK_Articles] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Jest to prosta tabela z kluczem głównym oraz jedną kolumną (cena). Napiszmy wyzwalacz, w którym za każdym razem, gdy dodajemy nowy wiersz, cena jest podwajana i kolejny wiersz jest dodawany:

CREATE TRIGGER [dbo].[OnArticleInserted]  
ON [dbo].[Articles]  
AFTER INSERT
AS    
  INSERT INTO Articles (Price) (SELECT Price*2 from inserted)

Nasz test z kolei będzie wyglądać następująco:

ALTER PROCEDURE [sampleTests].[testTrigger]
AS
BEGIN
  --Assemble
  exec tSQLt.FakeTable 'Articles'
  exec tSQLt.ApplyTrigger 'Articles', 'OnArticleInserted'

  create table ExpectedValues
  (
     Price integer
  )

  INSERT INTO ExpectedValues (Price) Values (6),(12)
  
  --Act
  INSERT INTO Articles (Price) Values (6)
  
  --Assert
  EXEC tSQLt.AssertEqualsTable @Expected = N'ExpectedValues',  @Actual = N'Articles'
  
END

Zawsze chcemy odizolowywać tabele. Z tego względu używamy FakeTable na “Articles”. W naszym przypadku, wyzwalacz operuje tylko na tej tabeli więc to wystarczy. W praktyce izolujemy wszystkie tabele z danego wyzwalacza.
Następnie wywołujemy ApplyTrigger. Wiemy, że FakeTable powoduje stworzenie mock’a, zatem wszystkie wyzwalacze domyślnie będą odizolowane. Wywołanie ApplyTrigger umożliwia selektywną aktywację wyzwalaczy.

Dalsza część kodu już wygląda analogicznie do innych testów. Wykonujemy INSERT INTO na Article, co spowoduje uruchomienie naszego wyzwalacza. Na końcu sprawdzamy, czy nowy wiersz faktycznie został dodany.

Unity 3d – wprowadzenie do skryptów

Dzisiaj napiszemy nasz pierwszy skrypt w Unity 3d.

Najpierw dodajmy jakiś element na scene, który potem będziemy mogli obracać za pomocą skryptu. W tym celu z menu głównego wybieramy  GameObject->3d Object-> Cube:

1

Następnie w celu dodania skryptu klikamy na “Assets” w panelu “Project” i wybieramy  Create->C# Script:

2

Zanim przejdziemy do edycji skryptu, warto upewnić się, że Visual Studio jest skonfigurowany jako narzędzie do pisania kodu. W tym celu wchodzimy do Edit->Preferences. External Script Editor powinien być ustawiony na VS:

3

Teraz możemy dwa razy kliknąć na skrypcie i Unity 3d odpali instancję Visual Studio w raz z szablonem nowo wygenerowanego skryptu:

public class SpinCube : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

Nas interesuje wyłącznie metoda Update, która jest odpalana w każdej ramce renderowania. To właśnie tam będą znajdować się wszelkie transformacje. Jeśli chcemy obracać obiektem wtedy należy skorzystać z pola “transform”:

public class SpinCube : MonoBehaviour
{
	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update ()
	{
             transform.Rotate(0, 1, 0);	
	}
}

Właśnie napisaliśmy nasz pierwszy skrypt. Musimy jednak go doczepić do jakiegoś obiektu. W naszym przypadku będzie to dodany wcześniej sześcian. Wystarczy na niego kliknąć i po prostu przeciągnąć skrypt:

4

Od tego momentu klasa SpinCube będzie wykonana w każdej ramce renderowania. Oczywiście ten sam skrypt możemy doczepiać do różnych obiektów. Po naciśnięci przycisku “Play”, sześcian zacznie obracać się.

Zwykle skrypty przyjmują jakieś parametry wejściowe. W naszym przypadku może to być prędkość obracania. Z punktu widzenia C#, jest to zwykłe pole publiczne:

public class SpinCube : MonoBehaviour
{
        public int Speed;

	void Start () {
	
	}
	
	// Update is called once per frame
	void Update ()
	{
        transform.Rotate(0, Speed, 0);	
	}
}

Po ponownym kliknięciu obiektu, zobaczymy, że “Speed” jest teraz konfigurowalny:

5