public void ShouldGenerateCorrectOutput()
        {
            // Arrange
            var fileName             = "test.txt";
            var expectedPropertyName = "Test";
            var expectedWords        = new[] { "foo", "bar" };
            var expectedTypeName     = "FriendlyWordsDotNet.FriendlyWords";

            var additionalText = new StringAdditionalText(fileName, string.Join(Environment.NewLine, expectedWords));

            ExecuteGenerator(new[] { additionalText }, out Compilation outputCompilation, out GeneratorDriverRunResult runResult);

            SemanticModel model = outputCompilation.GetSemanticModel(runResult.GeneratedTrees[0]);

            TestContext.WriteLine("Generated code:");
            TestContext.Write(runResult.GeneratedTrees[0]);

            using (new AssertionScope("Generator Output"))
            {
                runResult.Diagnostics.Should().BeEmpty("generator should not generate any diagnostic errors from a valid file");
                runResult.GeneratedTrees.Should().HaveCount(1, "generator should only generate a single syntax tree");
                outputCompilation.GetDiagnostics().Should().BeEmpty("output compilation should be valid");
            }

            // Class Assertions
            INamedTypeSymbol? @class = outputCompilation.GetTypeByMetadataName(expectedTypeName);

            @class.Should().NotBeNull("generator should create the type {0}", expectedTypeName);

            using (new AssertionScope())
            {
                @class !.TypeKind.Should().Be(TypeKind.Class, "type {0} should be a class", expectedTypeName);
                @class.DeclaredAccessibility.Should().Be(Accessibility.Public, "type {0} should be publicly accessible", expectedTypeName);
                @class.IsStatic.Should().BeFalse("type {0} should not be static", expectedTypeName);
                @class.IsSealed.Should().BeTrue("type {0} should be sealed", expectedTypeName);

                var classDeclaration = (ClassDeclarationSyntax)@class.DeclaringSyntaxReferences[0].GetSyntax();

                classDeclaration.Modifiers.Should().Contain(t => t.IsKind(SyntaxKind.PartialKeyword), "declaration of type {0} should have the partial modifier", expectedTypeName);
            }

            // Property Assertions
            IPropertySymbol?property = @class.GetProperty(expectedPropertyName);

            property.Should().NotBeNull("property {0} should be generated", expectedPropertyName);

            using (new AssertionScope())
            {
                property !.IsStatic.Should().BeTrue("property {0} should be static", expectedPropertyName);
                property.IsReadOnly.Should().BeTrue("property {0} should only have a getter", expectedPropertyName);
                property.DeclaredAccessibility.Should().Be(Accessibility.Public, "property {0} should be publicly accessible", expectedPropertyName);

                ITypeSymbol expectedPropertyType = outputCompilation.GetSymbolForType <IReadOnlyCollection <string> >();

                property.Type.Should().Be(expectedPropertyType, "property {0} should be of type {1}", expectedPropertyName, expectedPropertyType);

                property.DeclaringSyntaxReferences.Should().HaveCount(1, "property {0} should only be declared a single time", expectedPropertyName);
            }

            // Property Initializer Assertions
            using (new AssertionScope())
            {
                var propertyNode = (PropertyDeclarationSyntax)property.DeclaringSyntaxReferences[0].GetSyntax();

                propertyNode.Initializer.Should().NotBeNull("property {0} should have an initializer", expectedPropertyName);

                propertyNode.Initializer !.Value.IsKind(SyntaxKind.ObjectCreationExpression).Should().BeTrue("initializer for property {0} should be an object creation expression", expectedPropertyName);

                var objectCreation = (ObjectCreationExpressionSyntax)propertyNode.Initializer.Value;

                ISymbol objectTypeSymbol = model.GetSymbolInfo(objectCreation.Type).Symbol !;

                ITypeSymbol expectedInitializerObjectType = outputCompilation.GetSymbolForType <ReadOnlyCollection <string> >();

                objectTypeSymbol.Should().Be(expectedInitializerObjectType, "initializer for property {0} should create an instance of {1}", expectedPropertyName, expectedInitializerObjectType);

                SeparatedSyntaxList <ArgumentSyntax> args = objectCreation.ArgumentList !.Arguments;

                args.Should().HaveCount(1);

                ArgumentSyntax argument = args.First();

                var arrayCreationExpression = (ImplicitArrayCreationExpressionSyntax)argument.Expression;

                arrayCreationExpression.Initializer.Expressions.Should().AllBeOfType <LiteralExpressionSyntax>().And.OnlyContain(l => l.IsKind(SyntaxKind.StringLiteralExpression), "initialized array should only contain strings");
                arrayCreationExpression.Initializer.Expressions.OfType <LiteralExpressionSyntax>().Select(e => e.Token.ValueText).Should().BeEquivalentTo(expectedWords, "initialized array should contain all the words from the AdditionalText");
            }
        }