public void ClassConstructorTest()
        {
            string assemblyname = "C:\\test\\TestAssembly.dll";
            string classname = "TestClass";

            var target = new Class(assemblyname, classname);

            Assert.AreEqual(assemblyname, target.AssemblyName, "Not equal");
            Assert.AreEqual("TestAssembly.dll", target.ShortAssemblyName, "Not equal");
            Assert.AreEqual(classname, target.Name, "Not equal");
        }
        public void EqualsTest()
        {
            string assemblyname = "TestAssembly";
            string classname = "TestClass";

            var target1 = new Class(assemblyname, classname);
            var target2 = new Class(assemblyname, classname);

            Assert.IsTrue(target1.Equals(target2), "Objects are not equal");

            Assert.IsFalse(target1.Equals(null), "Objects are equal");

            Assert.IsFalse(target1.Equals(new object()), "Objects are equal");
        }
        /// <summary>
        /// Starts the generation of the report.
        /// </summary>
        public void CreateReport()
        {
            int numberOfClasses = 0;
            var assemblies = new List<Assembly>();

            foreach (var assemblyName in this.parser.Assemblies())
            {
                var assembly = new Assembly(assemblyName);
                var classes = this.parser.ClassesInAssembly(assemblyName);

                foreach (var className in classes)
                {
                    var clazz = new Class(assembly.Name, className);
                    assembly.AddClass(clazz);
                    numberOfClasses++;
                }

                assemblies.Add(assembly);
            }

            logger.InfoFormat("Analyzing {0} classes", numberOfClasses);

            int counter = 0;

            if (this.rendererFactory.SupportsParallelClassReports)
            {
                Parallel.ForEach(
                    assemblies,
                    (assembly) =>
                    {
                        Parallel.ForEach(
                            assembly.Classes,
                            (clazz) =>
                            {
                                int current = Interlocked.Increment(ref counter);

                                logger.InfoFormat(
                                    CultureInfo.InvariantCulture,
                                    " Creating report {0}/{1} (Assembly: {2}, Class: {3})",
                                    current,
                                    numberOfClasses,
                                    clazz.AssemblyName,
                                    clazz.Name);

                                this.CreateClassReport(clazz);
                            });
                    });
            }
            else
            {
                foreach (var assembly in assemblies)
                {
                    foreach (var clazz in assembly.Classes)
                    {
                        logger.DebugFormat(
                            CultureInfo.InvariantCulture,
                            " Creating report {0}/{1} (Assembly: {2}, Class: {3})",
                            ++counter,
                            numberOfClasses,
                            clazz.AssemblyName,
                            clazz.Name);

                        this.CreateClassReport(clazz);
                    }
                }
            }

            this.CreateSummary(assemblies);
        }
        /// <summary>
        /// Adds the coverage information of a class to the report.
        /// </summary>
        /// <param name="clazz">The class.</param>
        public void SummaryClass(Class clazz)
        {
            string row = string.Format(
                CultureInfo.InvariantCulture,
                @"{0} & {1}\%\\",
                EscapeLatexChars(clazz.Name),
                clazz.CoverageQuota);

            this.reportBuilder.AppendLine(row);
        }
        /// <summary>
        /// Creates the report for the given class.
        /// </summary>
        /// <param name="clazz">The class.</param>
        private void CreateClassReport(Class clazz)
        {
            var files = this.parser.FilesOfClass(clazz.AssemblyName, clazz.Name);

            var fileAnalysis = files.Select(f => this.AnalyzeFile(f, clazz)).ToArray();

            if (!fileAnalysis.Any())
            {
                clazz.CoverageQuota = this.parser.GetCoverageQuotaOfClass(clazz.AssemblyName, clazz.Name);
                clazz.CoverageType = CoverageType.MethodCoverage;
            }

            var classRenderer = this.rendererFactory.CreateClassRenderer();

            if (classRenderer == null)
            {
                return;
            }

            classRenderer.BeginClassReport(clazz.Name);

            classRenderer.Header("Summary");

            classRenderer.BeginKeyValueTable();
            classRenderer.KeyValueRow("Class:", clazz.Name);
            classRenderer.KeyValueRow("Assembly:", clazz.ShortAssemblyName);
            classRenderer.KeyValueRow("File(s):", files);
            classRenderer.KeyValueRow("Coverage:", clazz.CoverageQuota.ToString(CultureInfo.InvariantCulture) + "%");
            classRenderer.KeyValueRow("Covered lines:", clazz.CoveredLines.ToString(CultureInfo.InvariantCulture));
            classRenderer.KeyValueRow("Coverable lines:", clazz.CoverableLines.ToString(CultureInfo.InvariantCulture));
            classRenderer.KeyValueRow("Total lines:", clazz.TotalLines.ToString(CultureInfo.InvariantCulture));
            classRenderer.FinishTable();

            var metrics = this.parser.MethodMetrics(clazz.AssemblyName, clazz.Name);

            if (metrics != null && metrics.Any())
            {
                classRenderer.Header("Metrics");

                classRenderer.BeginMetricsTable(new[] { "Method" }.Union(metrics.First().Metrics.Select(m => m.Name)));

                foreach (var metric in metrics)
                {
                    classRenderer.MetricsRow(metric);
                }

                classRenderer.FinishTable();
            }

            classRenderer.Header("File(s)");

            if (fileAnalysis.Any())
            {
                foreach (var file in fileAnalysis)
                {
                    classRenderer.File(file.FileName);

                    if (!string.IsNullOrEmpty(file.Error))
                    {
                        classRenderer.Paragraph(file.Error);
                    }
                    else
                    {
                        classRenderer.BeginLineAnalysisTable(new[] { string.Empty, "#", "Line", "Coverage" });

                        foreach (var line in file.Lines)
                        {
                            classRenderer.LineAnalysis(line);
                        }

                        classRenderer.FinishTable();
                    }
                }
            }
            else
            {
                classRenderer.Paragraph("No files found. This usually happens if a file isn't covered by a test or the class does not contain any sequence points (e.g. a class that only contains auto properties).");
            }

            classRenderer.SaveClassReport(this.targetDirectory, clazz.ShortAssemblyName, clazz.Name);
        }
        /// <summary>
        /// Analyses a file and generates a coverage report of the file.
        /// </summary>
        /// <param name="fileName">The name of the file.</param>
        /// <param name="clazz">The name of the assembly.</param>
        /// <returns>The generated coverage report of the given file.</returns>
        private FileAnalysis AnalyzeFile(string fileName, Class clazz)
        {
            if (!File.Exists(fileName))
            {
                string error = string.Format(CultureInfo.InvariantCulture, "File '{0}' does not exist (any more).", fileName);
                logger.Error(error);
                return new FileAnalysis(fileName, error);
            }

            try
            {
                string[] lines = File.ReadAllLines(fileName);

                clazz.TotalLines += lines.Length;

                int currentLineNumber = 0;

                var result = new FileAnalysis(fileName);

                foreach (var line in lines)
                {
                    int visits = this.parser.NumberOfLineVisits(clazz.AssemblyName, clazz.Name, fileName, ++currentLineNumber);

                    if (visits == 0)
                    {
                        clazz.CoverableLines++;
                    }
                    else if (visits > 0)
                    {
                        clazz.CoveredLines++;
                        clazz.CoverableLines++;
                    }

                    result.AddLineAnalysis(new LineAnalysis(visits, currentLineNumber, line.TrimEnd()));
                }

                return result;
            }
            catch (IOException ex)
            {
                string error = string.Format(CultureInfo.InvariantCulture, "Error during reading file '{0}': {1}", fileName, ex.Message);
                logger.Error(error);
                return new FileAnalysis(fileName, error);
            }
        }
 /// <summary>
 /// Addes the given class to the assembly.
 /// </summary>
 /// <param name="clazz">The class to add.</param>
 public void AddClass(Class clazz)
 {
     this.classes.Add(clazz);
 }
 /// <summary>
 /// Adds the coverage information of a class to the report.
 /// </summary>
 /// <param name="clazz">The class.</param>
 public void SummaryClass(Class clazz)
 {
     this.reportBuilder.AppendFormat(
         CultureInfo.InvariantCulture,
         "<tr class=\"classrow\"><td><a href=\"{0}\">{1}</a></td><td title=\"{2}\">{3}%</td><td>{4}</td></tr>",
         WebUtility.HtmlEncode(ReplaceInvalidPathChars(clazz.ShortAssemblyName + "_" + clazz.Name) + ".htm"),
         WebUtility.HtmlEncode(clazz.Name),
         clazz.CoverageType,
         clazz.CoverageQuota,
         CreateCoverageTable(clazz.CoverageQuota));
 }
        /// <summary>
        /// Adds the coverage information of a class to the report.
        /// </summary>
        /// <param name="clazz">The class.</param>
        public void SummaryClass(Class clazz)
        {
            var coverage = new XElement(
                "Class",
                new XAttribute("name", clazz.Name),
                new XAttribute("coverage", clazz.CoverageQuota),
                new XAttribute("coveredlines", clazz.CoveredLines),
                new XAttribute("coverablelines", clazz.CoverableLines),
                new XAttribute("totallines", clazz.TotalLines));

            this.currentAssembly.Add(coverage);
        }