#if (odwołanie w C#)

0

Chcemy aby nasza aplikacja działała w trzech środowiskach.

  1. Lokalnie - DEBUG
  2. Serwer testowy - ????
  3. Serwer produkcyjny - RELEASE

Dla każdej konfiguracji mam zmiany w web.config oraz bezpośrednio w kodzie w formie #if DEBUG, #if RELEASE.

Dodałem sobie trzecią konfigurację DEVRELEASE, dla web.config mogę dodać konfigurację, ale nie mogę w kodzie odwołać się do #if DEVRELEASE.

Podejrzewam, że usiłuje błędnie wykorzystać konfigurację solucji - powinienem wszystko warunkować w web.config?

6

Jak już dodałeś w Configuration Management nową konfigurację to jeszcze w projekcie musisz dodać symbole:
Capture.PNG

0

Dziękuję za wytłumaczenie, brakowało symbolu.

4

Powodzenia w automatycznym testowaniu kodu kompilowanego warunkowo.

2

Nie rozumiem. Najpierw piszesz, że kod kompilowany warunkowo jest ciężko testować, potem że działanie powinno być zależne od konfiguracji (czyli kompilacja warunkowa). Wyjaśnij.

Konfiguracja aplikacji to nie jest kompilacja warunkowa, nie rozumiem dlaczego to utożsamiasz, kiedy są to niemal rozłączne tematy. Miałem na myśli *.config itp. Pobieranie konfiguracji możesz przykryć testem, działanie na dowolnej wartości konfiguracji zamockować i też przykryć testem (test case'm).

Kompilacja warunkowa dla zmiany private na public wydaje mi się dość karkołomna.
Prywatnych metod niby nie powinno się testować, ale jeśli z pewnych powodów musisz (np. dla prostoty testów), to zmień im private na internal i zaprzyjaźnij z assembly framework od testów/mocków, ewentualnie wydziel je do osobnej klasy.

1

Po pierwsze źle zadane pytanie. Po co ci ta kompilacja warunkowa? Co chcesz tym osiągnąć?
Po drugie kod kompilowany inaczej na serwer testowy to proszenie się o kłopoty.
Wystarczy, że przez pomyłkę, ktoś w sekcji kompilacji warunkowej wprowadzi side effct i spędzisz miesiąc na szukanie błędu, bo na produkcji występuje, a na serwerze testowym wszystko działa (lub odwrotnie jeśli masz szczęście).
Po trzecie, chciałbyś zmienić coś by na serwerze testowych coś działało jak na serwerze produkcyjnym i musisz wgrywać nową wersję zamiast zmienić tylko opcję konfiguracyjną. W przypadku problemów poprzedniego typu czas poszukiwań źródeł problemu zostanie znacznie wydłużony (za każdym razem wgrywasz od początku inną wersje).

1

@Juhas:

  1. Skoro tak robisz, to testujesz INNY kod niż wrzucasz na produkcję. Twoje testy są nic nie warte i możesz je skasować.
  2. W przypadku prawidłowego projektu aplikacji nie ma problemu z dostarczeniem losowych danych do testów, a prawdziwych do pracy. Kwestia oddzielenia źródła danych od algorytmów na nich operujących, czyli trzymanie się zasady jednej odpowiedzialności i używanie interfejsów.
  3. Metody prywatne testują się przy okazji testowania metod publicznych. Jeżeli metoda prywatna zawiera logikę tak skomplikowaną, że trzeba ją testować oddzielnie, to znaczy, że klasa łamie zasadę jednej odpowiedzialności. Metoda prywatna powinna zostać wydzielona do oddzielnej klasy i testowana niezależnie.
0
somekind napisał(a):

@Juhas:

  1. Skoro tak robisz, to testujesz INNY kod niż wrzucasz na produkcję. Twoje testy są nic nie warte i możesz je skasować.

Uspokój się, to są jednostkowe przypadki. 2, 3 metody w całym systemie.

  1. W przypadku prawidłowego projektu aplikacji nie ma problemu z dostarczeniem losowych danych do testów, a prawdziwych do pracy. Kwestia oddzielenia źródła danych od algorytmów na nich operujących, czyli trzymanie się zasady jednej odpowiedzialności i używanie interfejsów.

Tu chodzi o coś innego. Normalnie dane mają być losowe. Ale do testów muszę mieć konkretne. No można to zrobić inaczej faktycznie. Ale z drugiej strony tworzyć osobne klasy, które służą tylko do tego, żeby dać losowego albo konkretnego integera?

  1. Metody prywatne testują się przy okazji testowania metod publicznych. Jeżeli metoda prywatna zawiera logikę tak skomplikowaną, że trzeba ją testować oddzielnie, to znaczy, że klasa łamie zasadę jednej odpowiedzialności. Metoda prywatna powinna zostać wydzielona do oddzielnej klasy i testowana niezależnie.

Poniekąd się zgadzam (że testujemy tylko metody publiczne). Ale jeśli metoda prywatna zawiera fragment kodu, który jest dość istotny, to nie za bardzo widzę inną możliwość (poza opisanym wyżej internal albo refleksją).

0
somekind napisał(a):

Metody prywatne testują się przy okazji testowania metod publicznych.

Czasami osobne testy metod publicznych z partial mockami metod prywatnych + osobne testy metod prywatnych bardzo, ale to bardzo upraszczają testy. Zamiast przygotowywać pełen zestaw danych robisz jego węższe zbiory. Takie testy są łatwiejsze do utrzymania, bo jeśli zmienisz małą metodę, to poprawiasz tylko krótki, a zatem czytelny test do niej.
Oczywiście wszystko ma swoje plusy i minusy, tutaj rezygnujesz z pełnej enkapsulacji bebechów obiektu zamieniając private na internal i używasz partial mocków, które potrafią działać trochę koślawo.

0
Juhas napisał(a):
  1. W przypadku prawidłowego projektu aplikacji nie ma problemu z dostarczeniem losowych danych do testów, a prawdziwych do pracy. Kwestia oddzielenia źródła danych od algorytmów na nich operujących, czyli trzymanie się zasady jednej odpowiedzialności i używanie interfejsów.

Tu chodzi o coś innego. Normalnie dane mają być losowe. Ale do testów muszę mieć konkretne. No można to zrobić inaczej faktycznie. Ale z drugiej strony tworzyć osobne klasy, które służą tylko do tego, żeby dać losowego albo konkretnego integera?

Cała klasa dla losowej liczby? Przecież to załatwia jedna zmienna wewnątrz metody będącej testem. Natomiast nie tędy droga, bo losowość danych testowych spowoduje losowość poprawności testu, innymi słowy test może się nie wywalić na błędzie, czyli jest do d**y. Test powinien przykryć przypadek pozytywny, przypadki brzegowe (nulle, zera itp) i negatywne - oprogramowane błędy (czyli np. w dostarczonej liście nie będzie określonych danych i wtedy zostaje wywołany logger, a z metody leci na zewnątrz określony wyjątek). Nie ma w tym miejsca na losowe dane.

1
Juhas napisał(a):

Uspokój się, to są jednostkowe przypadki. 2, 3 metody w całym systemie.

W Twoim świecie tylko niespokojni piszą prawdę?

Tu chodzi o coś innego. Normalnie dane mają być losowe. Ale do testów muszę mieć konkretne. No można to zrobić inaczej faktycznie. Ale z drugiej strony tworzyć osobne klasy, które służą tylko do tego, żeby dać losowego albo konkretnego integera?

Tak tak się pisze testy jednostkowe na całym świecie.
W tym konkretnym przypadku: klasa dostaje w zależnościach interfejs, który ma metodę zwracającą inta. W produkcyjnym kodzie używana jest klasa zwracająca losową liczbę. W testach używany jest mock, który zwraca konkretną wartość.

Poniekąd się zgadzam (że testujemy tylko metody publiczne). Ale jeśli metoda prywatna zawiera fragment kodu, który jest dość istotny, to nie za bardzo widzę inną możliwość (poza opisanym wyżej internal albo refleksją).

Jak napisałem - taka metoda nie powinna być prywatna, tylko powinna być publiczną metodą swojej własnej klasy.

ŁF napisał(a):

Czasami osobne testy metod publicznych z partial mockami metod prywatnych + osobne testy metod prywatnych bardzo, ale to bardzo upraszczają testy.

Najprostsze testy są wtedy, gdy wszystkie metody i pola są publiczne. Tylko nie o to chyba chodzi w programowaniu.

Zamiast przygotowywać pełen zestaw danych robisz jego węższe zbiory. Takie testy są łatwiejsze do utrzymania, bo jeśli zmienisz małą metodę, to poprawiasz tylko krótki, a zatem czytelny test do niej.

I w czym to jest lepsze od SRP?

0
somekind napisał(a):
ŁF napisał(a):

Czasami osobne testy metod publicznych z partial mockami metod prywatnych + osobne testy metod prywatnych bardzo, ale to bardzo upraszczają testy.

Najprostsze testy są wtedy, gdy wszystkie metody i pola są publiczne. Tylko nie o to chyba chodzi w programowaniu.

Zamiast przygotowywać pełen zestaw danych robisz jego węższe zbiory. Takie testy są łatwiejsze do utrzymania, bo jeśli zmienisz małą metodę, to poprawiasz tylko krótki, a zatem czytelny test do niej.

I w czym to jest lepsze od SRP?

Są przecież "węższe" modyfikatory dostępu. Wszystko kwestią zdrowego rozsądku.
Co do SRP - jeszcze nie spotkałem w swoim życiu kodu, który by był napisany zgodnie z tą regułą, co najwyżej drobna część klas. Większość programistów tego nie opanowała, ponadto zwykle nie ma czasu na refactoring już istniejącego systemu (w dodatku kierownik powie, że może to wprowadzić nowe błędy), więc dokłada się kolejne funkcjonalności wciskając je pomiędzy już napisane i raptem - puff! - SRP znika. O ile w ogóle było.

1 użytkowników online, w tym zalogowanych: 0, gości: 1