Applied Programming/Testing/C Sharp

Test.csproj

edit
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <RootNamespace>Temperature</RootNamespace>
    <GenerateProgramFile>false</GenerateProgramFile>
    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
    <PackageReference Include="xunit" Version="2.4.1" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="coverlet.collector" Version="1.3.0">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>

</Project>

Temperature.cs

edit
/// <summary>
/// This program asks the user for a Fahrenheit temperature, 
/// converts the given temperature to Celsius,
/// and displays the results.
///
/// Input:
///     Fahrenheit temperature
///
/// Output:
///     Fahrenheit temperature
///    Celsius temperature
///
/// Example:
///    Enter Fahrenheit temperature:
///    100
///    100.0° Fahrenheit is 37.8° Celsius
///
/// References:
///     https://www.mathsisfun.com/temperature-conversion.html
///     https://en.wikibooks.org/wiki/C_Sharp_Programming
///     https://en.wikiversity.org/wiki/Applied_Programming/Functions/Python3
///     https://en.wikiversity.org/wiki/Programming_Fundamentals/Functions/C_Sharp
///     https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions
///     https://www.dofactory.com/reference/csharp-coding-standards
/// </summary>

using System;

namespace Temperature
{
    class Temperature
    {
        const int TemperatureDifference = 32;
        const double TemperatureRatio = 5.0 / 9.0;
        const double AbsoluteZero = -459.67;

        /// <summary>Runs the main program logic.</summary>
        public static void Main(string[] args)
        {
            while(true)
            {
                Console.Clear();
                var fahrenheit = GetFahrenheit();
                var celsius = ConvertFahrenheitToCelsius(fahrenheit);
                DisplayResult(fahrenheit, celsius);

                Console.WriteLine("Would you like to convert another temperature? Y or N");
                var input = Console.ReadLine();
                if (input != "Y") 
                { 
                    break;
                }
            }
        }

        /// <summary>Gets Fahrenheit temperature.</summary>
        /// <returns>Returns Fahrenheit temperature.</returns>
        /// <exception cref="System.ArgumentOutOfRangeException">
        ///    Thrown when entered temperature is below absolute zero.
        /// </exception>
        /// <exception cref="System.FormatException">
        ///    Thrown when entered temperature is not a valid floating point value.
        /// </exception>
        public static double GetFahrenheit()
        {
            while(true)
            {
                Console.WriteLine("Enter Fahrenheit temperature: ");
                var input = Console.ReadLine();

                try
                {
                    var fahrenheit = Convert.ToDouble(input);
                    if (fahrenheit < AbsoluteZero)
                    {
                        Console.WriteLine("Fahrenheit temperature cannot be below absolute zero.");
                        Console.WriteLine($"ArgumentOutOfRangeException: '{fahrenheit}' is invalid.");
                    }
                    else
                    {
                        return fahrenheit;
                    }
                }
                catch (System.FormatException)
                {
                    Console.WriteLine("Fahrenheit temperature must be a floating point value.");
                    Console.WriteLine($"FormatException: '{input}' is invalid.");
                }
            }
        }

        /// <summary>Calculates Celsius temperature.</summary>
        /// <param name="fahrenheit">Fahrenheit temperature.</param>
        /// <returns>Returns Celsius temperature.</returns>
        public static double ConvertFahrenheitToCelsius(double fahrenheit)
        {
            System.Diagnostics.Debug.Assert(fahrenheit >= AbsoluteZero);

            var celsius = (fahrenheit - TemperatureDifference) * TemperatureRatio;

            return celsius;
        }

        /// <summary>Displays conversion results.</summary>
        /// <param name="fahrenheit">Fahrenheit temperature.</param>
        /// <param name="fahrenheit">Celsius temperature.</param>
        public static void DisplayResult(double fahrenheit, double celsius)
        {
            Console.WriteLine(fahrenheit.ToString() + "° Fahrenheit is " + celsius + "° Celsius");
        }
    }
}

TemperatureTest.cs

edit
// Temperature test code.
//
// Created using:
//  dotnet new xunit
//
// Test using:
//  dotnet test
//
// References:
//  https://docs.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-dotnet-test
//  https://docs.microsoft.com/en-us/dotnet/core/testing/unit-testing-best-practices
//  https://andrewlock.net/fixing-the-error-program-has-more-than-one-entry-point-defined-for-

using System;
using Xunit;

namespace Temperature
{
    public class TemperatureTests
    {
        [Fact]
        public void GetFahrenheit_Returns_Fahrenheit()
        {
            var input = new System.IO.StringReader("98.6");
            Console.SetIn(input);

            var output = new System.IO.StringWriter();
            Console.SetOut(output);

            var fahrenheit = Temperature.GetFahrenheit();
            Assert.Equal(98.6, fahrenheit);
        }

        [Fact]
        public void GetFahrenheit_BelowAbsoluteZero_DisplaysError()
        {
            var input = new System.IO.StringReader("-500\n0");
            Console.SetIn(input);

            var output = new System.IO.StringWriter();
            Console.SetOut(output);

            var fahrenheit = Temperature.GetFahrenheit();
            Assert.Contains("absolute zero", output.ToString());
            Assert.Contains("'-500' is invalid", output.ToString());
            Assert.Equal(0, fahrenheit);
        }

        [Fact]
        public void GetFahrenheit_String_DisplaysError()
        {
            var input = new System.IO.StringReader("x\n0");
            Console.SetIn(input);

            var output = new System.IO.StringWriter();
            Console.SetOut(output);

            var fahrenheit = Temperature.GetFahrenheit();
            Assert.Contains("floating point", output.ToString());
            Assert.Contains("'x' is invalid", output.ToString());
            Assert.Equal(0, fahrenheit);
        }

        [Fact]
        public void ConvertFahrenheitToCelsius_Converts_ToCelsius()
        {
            var input = new System.IO.StringReader("98.6");
            Console.SetIn(input);

            var output = new System.IO.StringWriter();
            Console.SetOut(output);

            var celsius = Temperature.ConvertFahrenheitToCelsius(98.6);
            Assert.Equal(37, celsius);
        }

        [Fact]
        public void DisplayResult_Displays_Result()
        {
            var output = new System.IO.StringWriter();
            Console.SetOut(output);

            Temperature.DisplayResult(98.6, 37.0);
            Assert.Contains("98.6° Fahrenheit is 37° Celsius", output.ToString());
        }
    }
}

Try It

edit
  1. Install the Microsoft .NET 5.0 SDK.
  2. Copy the the three files above and paste into a new local folder.
  3. Open a terminal window or command prompt in the local folder.
  4. Run the following command:
    dotnet test

See Also

edit