Konsolowe zadanie

Klasa Program.cs

using System;
using ObliczeniaTablica.Logika;

class Program
{
    static void Main()
    {
        Console.WriteLine("=== PROGRAM DO OBLICZEŃ ==="); // menu wyboru
        Console.WriteLine("1) W = (3x - 2) / (2y)");
        Console.WriteLine("2) Q = ((2x - 3) * y) / z");
        Console.WriteLine("3) AB = (2x - y)^2 / (3x + 2)");
        Console.WriteLine("4) AC = √((3x - 7)^2 / (2y))");
        Console.Write("Wybierz numer zadania (1-4): ");

        try
        {
            int wybor = int.Parse(Console.ReadLine()); 
            var zadanie = (Zadanie)wybor; // TU DOKONUJEMY WYBORU ZADANIA, jednocześnie
                                          // tu liczba z wyboru jest rzutowana (zamieniana) na typ wyliczeniowy
                                          //enum Zadanie (public enum Zadanie z LogikaObliczenia.cs
                                          // 

            // wczytujemy tylko potrzebne zmienne
            double x = 0, y = 0, z = 0; //ustawienia startowe

            Console.Write("Podaj x: ");
            x = LogikaObliczen.ParseDouble(Console.ReadLine());

            if (zadanie != Zadanie.Q && zadanie != Zadanie.AC && zadanie != Zadanie.W && zadanie != Zadanie.AB)
                throw new ArgumentOutOfRangeException(nameof(zadanie)); //tu sprawdzamy, czy zmienna zadanie
                                                        // NIE jest żadną z czterech dozwolonych opcji
                                                        // (W,Q,AB,AC)
                                                        // ostatnia linia jeśli wybór nie pasuje , wyrzuca błąd

            Console.Write("Podaj y: ");
            y = LogikaObliczen.ParseDouble(Console.ReadLine()); 

            if (zadanie == Zadanie.Q)  // jeśli użytkownik wybrał Q
            {
                Console.Write("Podaj z: "); // podajemy dodatkowo y
                z = LogikaObliczen.ParseDouble(Console.ReadLine());
            }

            double wynik = LogikaObliczen.Oblicz(zadanie, x, y, z); // tu przekazujemy wszystkie dane do LogikaObliczenia
                                                                    // do metody Oblicz

            Console.WriteLine("\n--- WYNIK ---");
            Console.WriteLine($"{zadanie}: {wynik:F6}");
        }
        catch (FormatException)
        {
            Console.WriteLine("Błąd: wprowadź poprawne liczby (np. 2.5 lub 2,5).");
        }
        catch (ArgumentException ex)
        {
            Console.WriteLine("Błąd danych: " + ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Nieoczekiwany błąd: " + ex.Message);
        }

        Console.WriteLine("\nNaciśnij dowolny klawisz, aby zakończyć...");
        Console.ReadKey();
    }
}

klasa LogikaObliczenia

using System;
using System.Globalization;
using ObliczeniaTablica.Walidacja;

namespace ObliczeniaTablica.Logika
{
    public enum Zadanie { W = 1, Q = 2, AB = 3, AC = 4 } //tu definiujemy typ wyliczeniowy dla Program.cs
                                                           // czyli jakby nowy typ danych ale z kilkama 
                                                           //konkretnymi wartościami (liczba-nazwa)
    public static class LogikaObliczen
    {
        // (1) W = (3x - 2) / (2y)
        public static double W(double x, double y)
        {
            WalidacjaWejscia.RzucGdyZero(y, nameof(y));
            return (3 * x - 2) / (2 * y);
        }

        // (2) Q = ((2x - 3) * y) / z
        public static double Q(double x, double y, double z)
        {
            WalidacjaWejscia.RzucGdyZero(z, nameof(z));
            return ((2 * x - 3) * y) / z;
        }

        // (3) AB = (2x - y)^2 / (3x + 2)
        public static double AB(double x, double y)
        {
            double mianownik = 3 * x + 2;
            WalidacjaWejscia.RzucGdyZero(mianownik, "3x + 2");
            double licznik = Math.Pow(2 * x - y, 2);
            return licznik / mianownik;
        }

        // (4) AC = sqrt( (3x - 7)^2 / (2y) )
        public static double AC(double x, double y)
        {
            double mianownik = 2 * y;
            WalidacjaWejscia.RzucGdyZero(mianownik, "2y");

            double licznik = Math.Pow(3 * x - 7, 2);
            double podPierwiastkiem = licznik / mianownik;

            if (podPierwiastkiem < 0)
                throw new ArgumentException("Wyrażenie pod pierwiastkiem jest ujemne.");

            return Math.Sqrt(podPierwiastkiem);
        }

        /// Nie wszystkie parametry są używane w każdym zadaniu.
        public static double Oblicz(Zadanie zadanie, double x, double y, double z)
        {
            return zadanie switch // Metoda Oblicz sama rozpoznaje które równanie wybrałeś
                                  // korzystając ze switch
                                  // parametry zmiennych uzupełniają odpowiednie metody
            {
                Zadanie.W => W(x, y),
                Zadanie.Q => Q(x, y, z),
                Zadanie.AB => AB(x, y),
                Zadanie.AC => AC(x, y),
                _ => throw new ArgumentOutOfRangeException(nameof(zadanie))
            };
        }

        /// Pomocnicze: bezpieczny parse akceptujący kropkę i przecinek.
        public static double ParseDouble(string input)
        {
            if (double.TryParse(input.Replace(',', '.'),
                                NumberStyles.Float,
                                CultureInfo.InvariantCulture,
                                out double val))
                return val;
            throw new FormatException("Niepoprawna liczba.");
        }
    }
}

Klasa WalidacjaWejscia.cs

using System;

namespace ObliczeniaTablica.Walidacja
{
    public static class WalidacjaWejscia
    {
        public static void RzucGdyZero(double wartosc, string nazwa)
        {
            if (wartosc == 0)
                throw new ArgumentException($"{nazwa} nie może być równe 0.");
        }
    }
}

TESTY JEDNOSTKOWE – krok po kroku

1) Dodaj drugi projekt (MSTest)

  1. Otwórz rozwiązanie z projektem ObliczeniaTablica (konsola).
  2. W Eksploratorze rozwiązań: PPM na Rozwiązanie ‘ObliczeniaTablica’Dodaj → Nowy projekt…
  3. Wyszukaj „test” i wybierz Projekt testu jednostkowego MSTest (.NET).
  4. Nazwa: ObliczeniaTablica.TestsUtwórz.
  5. Po utworzeniu w projekcie testowym pojawi się przykładowy plik testu — możesz go usunąć albo zastąpić własnym.

💡 Upewnij się, że oba projekty celują w ten sam framework (np. .NET 9):

  • PPM na projekt → WłaściwościAplikacja → Docelowa platforma .NET: ustaw .NET 9.0.
    Jeśli główny projekt ma net8.0-windows (to dotyczy WPF/WinForms), wtedy testy też ustaw na net9.0-windows albo dodaj drugi „target” — najprościej ustawić tak samo.

2) Podłącz projekt testów do projektu z logiką

  1. W projekcie ObliczeniaTablica.Tests: PPM na ZależnościDodaj odwołanie do projektu…
  2. Zaznacz ObliczeniaTablicaOK.

(To jest kluczowe — bez tego testy nie „widzą” klas z Twojej logiki.)


3) Utwórz plik z testami

Nazwij plik ObliczeniaTests.cs.
PPM na projekt ObliczeniaTablica.TestsDodaj → Nowy element…Klasa.

Klasa Obliczenia..Tests.cs

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using ObliczeniaTablica.Logika;  // odwołanie do Twojej logiki

namespace ObliczeniaTablica.Tests
{
    [TestClass]
    public class ObliczeniaTests
    {
        // --- Testy poprawnych wyników ---
        [TestMethod]
        public void W_Poprawny()
        {
            // (3*2-2)/(2*3) = 4/6 = 0.666...
            Assert.AreEqual(2.0 / 3.0, LogikaObliczen.W(2, 3), 1e-9);
        }

        [TestMethod]
        public void Q_Poprawny()
        {
            // ((2*2-3)*3)/4 = (1*3)/4 = 0.75
            Assert.AreEqual(0.75, LogikaObliczen.Q(2, 3, 4), 1e-9);
        }

        [TestMethod]
        public void AB_Poprawny()
        {
            // (2*2-3)^2/(3*2+2) = 1/8 = 0.125
            Assert.AreEqual(0.125, LogikaObliczen.AB(2, 3), 1e-9);
        }

        [TestMethod]
        public void AC_Poprawny()
        {
            // ((3*3-7)^2)/(2*2) = 4/4 = 1 => sqrt(1) = 1
            Assert.AreEqual(1.0, LogikaObliczen.AC(3, 2), 1e-9);
        }

        // --- Testy wyjątków (walidacja) ---
        [TestMethod]
        public void W_GdyYZero_Rzuca()
            => Assert.ThrowsException<ArgumentException>(() => LogikaObliczen.W(1, 0));

        [TestMethod]
        public void Q_GdyZZero_Rzuca()
            => Assert.ThrowsException<ArgumentException>(() => LogikaObliczen.Q(1, 2, 0));

        [TestMethod]
        public void AB_GdyMianownikZero_Rzuca()
            => Assert.ThrowsException<ArgumentException>(() => LogikaObliczen.AB(-2.0 / 3.0, 5));

        [TestMethod]
        public void AC_GdyPodPierwiastkiemUjemne_Rzuca()
            => Assert.ThrowsException<ArgumentException>(() => LogikaObliczen.AC(0, -1));

        // --- Test routera (menu) ---
        [TestMethod]
        public void Oblicz_W_ZwracaToSamoCoW()
        {
            double x = 2, y = 3;
            var a = LogikaObliczen.W(x, y);
            var b = LogikaObliczen.Oblicz(Zadanie.W, x, y, 0);
            Assert.AreEqual(a, b, 1e-12);
        }

        [TestMethod]
        public void Oblicz_Q_ZwracaToSamoCoQ()
        {
            double x = 2, y = 3, z = 4;
            var a = LogikaObliczen.Q(x, y, z);
            var b = LogikaObliczen.Oblicz(Zadanie.Q, x, y, z);
            Assert.AreEqual(a, b, 1e-12);
        }
    }
}

Assert.AreEqual – porównuje dwa wyniki, pierwszy to wartość oczekiwana, drugi to co faktycznie zwrócił