using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
public class SentimentAnalyzer
public static string ClassifyText(string text, Dictionary<string, Dictionary<string, int>> trainingData)
if (string.IsNullOrWhiteSpace(text))
throw new ArgumentException("Text cannot be null or empty.", nameof(text));
if (trainingData == null || trainingData.Count == 0)
throw new ArgumentException("Training data cannot be null or empty.", nameof(trainingData));
if (!trainingData.ContainsKey("positive") || !trainingData.ContainsKey("negative"))
throw new ArgumentException("Training data must contain 'positive' and 'negative' sentiments.", nameof(trainingData));
var sentiments = trainingData.Keys.ToList();
var probabilities = new Dictionary<string, double>();
var vocabulary = new HashSet<string>();
var totalWordsPerSentiment = new Dictionary<string, int>();
foreach (var sentiment in sentiments)
totalWordsPerSentiment[sentiment] = 0;
foreach (var wordCount in trainingData[sentiment])
vocabulary.Add(wordCount.Key);
totalWordsPerSentiment[sentiment] += wordCount.Value;
int vocabularySize = vocabulary.Count;
foreach (var sentiment in sentiments)
double logLikelihood = 0.0;
string[] words = text.Split(' ');
foreach (var word in words)
if (trainingData[sentiment].ContainsKey(word))
logLikelihood += Math.Log((double)(trainingData[sentiment][word] + 1) / (totalWordsPerSentiment[sentiment] + vocabularySize));
logLikelihood += Math.Log(1.0 / (totalWordsPerSentiment[sentiment] + vocabularySize));
probabilities[sentiment] = Math.Log(1.0 / sentiments.Count) + logLikelihood;
return probabilities["positive"] >= probabilities["negative"] ? "positive" : "negative";
public class SentimentAnalyzerTests
private Dictionary<string, Dictionary<string, int>> _trainingData;
_trainingData = new Dictionary<string, Dictionary<string, int>>
"positive", new Dictionary<string, int>
"negative", new Dictionary<string, int>
public void ClassifyText_PositiveText_ReturnsPositive()
string text = "good great awesome";
string sentiment = SentimentAnalyzer.ClassifyText(text, _trainingData);
Assert.AreEqual("positive", sentiment);
public void ClassifyText_NegativeText_ReturnsNegative()
string text = "bad terrible awful";
string sentiment = SentimentAnalyzer.ClassifyText(text, _trainingData);
Assert.AreEqual("negative", sentiment);
public void ClassifyText_MixedText_ReturnsPositive()
string text = "good bad great";
string sentiment = SentimentAnalyzer.ClassifyText(text, _trainingData);
Assert.AreEqual("positive", sentiment);
public void ClassifyText_UnknownWords_ReturnsPositive()
string text = "unknown words test";
string sentiment = SentimentAnalyzer.ClassifyText(text, _trainingData);
Assert.AreEqual("positive", sentiment);
public void ClassifyText_MoreNegativeWords_ReturnsNegative()
string text = "bad bad terrible";
var trainingData = new Dictionary<string, Dictionary<string, int>>
{ "positive", new Dictionary<string, int> { { "good", 1 } } },
{ "negative", new Dictionary<string, int> { { "bad", 2 }, { "terrible", 1 } } }
string sentiment = SentimentAnalyzer.ClassifyText(text, trainingData);
Assert.AreEqual("negative", sentiment);
[ExpectedException(typeof(ArgumentException))]
public void ClassifyText_NullText_ThrowsArgumentException()
SentimentAnalyzer.ClassifyText(null, _trainingData);
[ExpectedException(typeof(ArgumentException))]
public void ClassifyText_EmptyText_ThrowsArgumentException()
SentimentAnalyzer.ClassifyText("", _trainingData);
[ExpectedException(typeof(ArgumentException))]
public void ClassifyText_NullTrainingData_ThrowsArgumentException()
SentimentAnalyzer.ClassifyText("good", null);
[ExpectedException(typeof(ArgumentException))]
public void ClassifyText_EmptyTrainingData_ThrowsArgumentException()
SentimentAnalyzer.ClassifyText("good", new Dictionary<string, Dictionary<string, int>>());
[ExpectedException(typeof(ArgumentException))]
public void ClassifyText_MissingPositiveSentiment_ThrowsArgumentException()
var invalidTrainingData = new Dictionary<string, Dictionary<string, int>>
{ "negative", new Dictionary<string, int> { { "bad", 7 } } }
SentimentAnalyzer.ClassifyText("good", invalidTrainingData);
[ExpectedException(typeof(ArgumentException))]
public void ClassifyText_MissingNegativeSentiment_ThrowsArgumentException()
var invalidTrainingData = new Dictionary<string, Dictionary<string, int>>
{ "positive", new Dictionary<string, int> { { "good", 10 } } }
SentimentAnalyzer.ClassifyText("good", invalidTrainingData);
public static void Main()
Console.WriteLine("š Discovering and Running Tests...\n");
int totalPassed = 0, totalFailed = 0;
var testClasses = Assembly.GetExecutingAssembly()
.Where(t => t.GetCustomAttribute<TestClassAttribute>() != null);
foreach (var testClass in testClasses)
Console.WriteLine($"š Running tests in: {testClass.Name}");
(int passed, int failed) = RunTests(testClass);
Console.WriteLine("\nš FINAL SUMMARY:");
Console.WriteLine($"ā
Total Passed: {totalPassed}");
Console.WriteLine($"ā Total Failed: {totalFailed}");
Console.WriteLine($"š Total Tests: {totalPassed + totalFailed}");
Console.WriteLine("\nā
Test execution completed.");
private static (int passed, int failed) RunTests(Type testClassType)
object testInstance = Activator.CreateInstance(testClassType);
MethodInfo setupMethod = testClassType
.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.FirstOrDefault(m => m.GetCustomAttribute<TestInitializeAttribute>() != null);
MethodInfo[] testMethods = testClassType
.GetMethods(BindingFlags.Instance | BindingFlags.Public)
.Where(m => m.GetCustomAttribute<TestMethodAttribute>() != null)
int passed = 0, failed = 0;
foreach (var method in testMethods)
setupMethod?.Invoke(testInstance, null);
method.Invoke(testInstance, null);
Console.WriteLine($" ā
{method.Name} PASSED");
catch (TargetInvocationException ex)
Console.WriteLine($" ā {method.Name} FAILED: {ex.InnerException?.Message ?? ex.Message}");
Console.WriteLine($" ā ļø {method.Name} ERROR: {ex.Message}");