Testowanie klas niepublicznych

Odpowiedz Nowy wątek
2017-09-14 23:24
0

Cześć, dzisiaj pytanie o testowanie klas niepublicznych. Załóżmy, że tworzę sobie jakąś bibliotekę. Upubliczniam w niej klasy, które mogą być wykorzystywane w API. Jednak jest część klas, które muszą pozostać prywatne dla biblioteki (klienci API mają nawet o nich nie wiedzieć). Jak testować taką klasę? Gdy uruchamiam xUnit, to oczywiście nie mogę testować, bo klasa nie jest widoczna. I teraz widzę dwie opcje:

  1. Użyć refleksji
  2. Stworzyć nową konfigurację. Do debug i release dodać coś w stylu "TEST". I wtedy:
    #ifdef TEST
    public
    #endif
    class InnerClass
    {
    }

A jak Wy widzicie testowanie takich klas?

edytowany 1x, ostatnio: Adam Boduch, 2017-09-15 06:41
@Adam Boduch: problem z postem - formatowanie kodu - prawdopodobnie dyrektywny zniszczyły formatowanie. - Juhas 2017-09-14 23:25

Pozostało 580 znaków

2017-09-15 08:23

Ten problem został rozwiązany przez wprowadzenie atrybutu (w .net 2.0, wydawało mi się że później) który sprawia że klasy internal z SUT są widoczne dla projektu testowego

using System.Runtime.CompilerServices;

[assembly:InternalsVisibleTo("MyTests")]

https://stackoverflow.com/que[...]ifier-when-doing-unit-testing

także nie trzeba kombinować :)


#Dżunior React Devloper wanna be#
edytowany 2x, ostatnio: neves, 2017-09-15 08:38
O, nie wiedziałem o tym. Świetne, dzięki :) - Juhas 2017-09-15 10:24

Pozostało 580 znaków

2017-09-15 12:05
7

InternalsVisibleTo to rak, który się z kodu usuwa, a nie dodaje.

Problem testowania klas wewnętrznych istnieje wyłącznie wtedy, gdy zamiast testów jednostkowych (testujących jednostkę, czyli coś co dostarcza jakąś funkcję w aplikacji) pisze się testy klas (testujących kod klasy). Prawidłowy projekt aplikacji i prawidłowo użyte testy sprawiają, że takich kombinacji nie trzeba.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2017-09-15 16:25
0

@somekind: w takim razie powiedz mi jak mam przetestować klasę Calculator:

class Calculator
{
   public int Add(int x, int y)
   {
       return x + y;
   }
}

public class MyClass
{
    List<int> numbers;
    public void Add(int x)
    {
        numbers.Add(x);
    }

    public void Operate()
    {
        Calculator calc; //jakoś go pobieram
        //załóżmy, że na liście są dwie liczby
        int sum = calc.Add(numbers[0], numbers[1]);

        JakisInnyObiekt obj; //jakoś go pobieram
        obj.DoWork(sum);
    }
}

Powiedz mi jak w mam przetestować metody z klasy Calculator bez używania InternalsVisibleTo. Przecież projekt testowy jest w innym assembly i nie ma dojścia do klasy Calculator.

Pozostało 580 znaków

2017-09-15 16:57
4

@Juhas: A dlaczego chcesz testować Calculator.Add(...) zamiast MyClass.Operate(...)?

Pozostało 580 znaków

2017-09-15 18:19
3

Uprzedzając następną odpowiedź: Jeśli Calculator ma skomplikowaną logikę niezależną od MyClass, to powinien znajdować się w oddzielnym module. Wówczas problem z testowaniem też nie istnieje.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2017-09-15 20:35
0

No zaraz. Testy jednostkowe polegają na testowaniu małych fragmentów. Dlatego chcę testować Add, żeby wiedzieć, że działa. Jeśli przetestowałbym MyClass.Operate i coś by było nie tak, to nie wiem, co jest nie tak. Czy nie działa Calculator, czy może JakisInnyObiekt, a może coś jeszcze innego.

Calculator to klasa przykładowa. Składnik konkretnego modułu. Więc czemu mam ją wywalić do innego modułu?

Pozostało 580 znaków

2017-09-15 21:17
0

Testy jednostkowe polegają na testowaniu małych fragmentów

Gdzie znalazłeś taką definicję?
Definicja z książki The Art of Unit Testing:

A unit test is a piece of code that invokes a unit of work and checks one specific end result of that unit of work. If the assumptions on the end result turn out to be wrong, the unit test has failed. A unit test’s scope can span as little as a method or as much as multiple classes.

Piszesz jeszcze:

Jeśli przetestowałbym MyClass.Operate i coś by było nie tak, to nie wiem, co jest nie tak. Czy nie działa Calculator, czy może JakisInnyObiekt

Ale jakie to ma znaczenie? Dobry test i tak by Ci to wychwycił. A tak:
a) zakładając, że masz testy tylko do Calculator.Add(...) a nieprawidłowe zachowanie będzie właśnie w JakisInnyObiekt to i tak nie będziesz o tym wiedział.
b) zakładając, że masz testy do Calculator.Add(...) i JakisInnyObiekt - nie zagwarantujesz w żaden sposób, że MyClass.Operate(...) wywołuje je poprawnie.
c) masz testy na Calculator.Add(...), JakisInnyObiekt oraz MyClass.Operate(...) - łamiesz pewnie DRY.

edytowany 1x, ostatnio: mstl, 2017-09-15 23:02
W unit testeach nie ma czegos takiego jak lamanie DRY :) - tamtamtu 2017-09-17 03:14

Pozostało 580 znaków

2017-09-15 22:03
0

Nie mam testów na MyClass.Operate. W zupełności wystarczają mi te dwa pozostałe. Poza tym wszędzie czytam, że jeśli chodzi o pisanie testów, to DRY nie ma znaczenia. Test powinien być jak najprostszy, żeby zminimalizować możliwość wystąpienia błędu w teście. Więc jak to w końcu jest? Bo coraz częściej mam wrażenie, że każdy zupełnie inaczej postrzega testy i każdy ma do nich zupełnie inne podejście.

Pozostało 580 znaków

2017-09-15 22:40
0

Poza tym wszędzie czytam, że jeśli chodzi o pisanie testów, to DRY nie ma znaczenia.

Oczywiście, każdy przecież lubi po drobnych zmianach w kodzie produkcyjnym poprawiać kod w 30 różnych miejscach w testach. A z TDD to jeszcze lepiej współgra.

Pozostało 580 znaków

2017-09-15 23:01
0

Staram się w testach trzymać DRY, jednak już w kilku miejscach czytałem, że testy są na tyle specyficzne, że DRY nie ma w nich większego znaczenia.
Nie piszę testów na co dzień. Właściwie to w pracy w ogóle ich nie piszę. Zajmuję się innymi rzeczami. Potrzebuję tego wszystkiego do własnego projektu.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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