Giter VIP home page Giter VIP logo

firefox-code-coverage-frontend's Introduction

Firefox code coverage diff viewer

This project is the code coverage changeset viewer for Firefox. You can view the frontend running in here.

To understand the big picture of code coverage at Mozilla read this blog post.

The app will show recent changesets from mozilla-central that have code coverage (pending changesets will be automatically be fetched). From there you can navigate to the diff of each changeset and see the code coverage for added lines. It is very important to reiterate that it is code coverage for added lines and not for a specific file (as most code coverage viewers focus on).

The data used in this UI is based on data submitted to codecov.io.

Planning and views

This is document tracks the original plans while these track grid view of plans and long term plans. You view all coverage collection work tracked in here. You can preview this app here while over here we track files without any coverage.

Disclaimers

  • Linux 64-bit and Windows 64-bit only.
    • partial debug build type: some flags are disabled
    • debug only tests are run
  • A few tests are disabled on coverage builds due to high failures
  • We ignore C++ files generated from IDL, IPDL, WebIDL
  • Coverage collections are for .c*, .h*, and .js* files
    • However, not all of these are covered (either no coverage or zero coverage)
    • Some of these are because we don't cover all platforms
  • Intermittent failures during testing cause different code paths to be hit (such as crash reporting)
  • Broken builds/failures might prevent us from running a test, set of tests, or a few jobs, coverage could be abnormally low

Filing issues

You can file frontend issues in Firefox code coverage frontend. For backend issues file them in releng-services with the 4.app: shipit_code_coverage label.

Requirements

Set up

Checkout the code and run:

yarn install
yarn start

Attribution

Icons from Material Design Icons.

firefox-code-coverage-frontend's People

Contributors

abhaychawla avatar akansha2608 avatar armenzg avatar csd713 avatar dottori avatar jankeromnes avatar jhkren avatar linkaiqi avatar marco-c avatar mozilla-github-standards avatar renovate-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

firefox-code-coverage-frontend's Issues

Main view polish

List of changes:

  • linkify bug numbers
  • removes authors' emails (instead of using substring)
  • pushes with net-new coverage
  • allow requesting more changesets (button at bottom saying "load more pushes")
  • spinner when loading the main view

Commit history with code coverage summary

To do

  • load code coverage status for each m-c push

Blockers

Notes

Plan disccused here:
https://public.etherpad-mozilla.org/p/code_coverage_Q3_17

I'm pasting over here some conversations we've had around the topic.

Armen wrote:

We will only be able to show accurate code coverage data for the latest version of a file
and/or test. If there are multiple changesets on a m-c push touching the same file or
related tests we will not be able to give accurate code coverage information for the older
changesets. Did I understand correctly?

gmierz wrote:

A strategy for getting around the multiple change sets for a single file could be to mark
what changeset each of the changes come from. That way, if we just use the latest file
in the current m-c push and the latest in the previous m-c push, there should be no
issues. But you are right to say "only" because this doesn't necessarily give us coverage
data from those patches exactly. I think this would be the best way to get around the
problem for now though.

What we hope to be able to use, ideally, to fix this is changeset algebra. Kyle, and I have
been playing with this idea and he's made a nice data structure that can take code
coverage backwards in changesets. I'll write down an example to illustrate this to you
tonight because it's not easy to explain in words. And we'll have to wait before we can
use it so we can test this idea a bit more.

Marco wrote:

Yes, this is correct. In some cases, we might be able to also say something about the
intermediate commits. For example, if commit A and commit B both change the same
file but not the same lines, then we can try to find the lines modified by A in the last
revision by taking into account the additions/removals made by B.

In the case where they both modify exactly the same line, we only really care about
the end result. If the line is covered, then it doesn't matter if it wasn't covered in A,
as long as it is covered in the end. If the line is not covered, then we will blame both A
and B as introducing an uncovered line.

Kyle wrote:

For our current implementation plan this understanding is correct, but it is not correct
in general: Code coverage can be mapped from one revision to another; even in the
case of multiple changes to the same file: The solution is to treat files as points in a
vector space; convert changesets to (orthogonal, binary) matrices; which allows us
to map coverage vectors from one revision to another, forward or backward.
We use that coverage to either make claims about total coverage, or claims about
coverage on net new lines, or combine multiple coverage runs for a more-stable
coverage statistic.

Kyle wrote:

The math is just a tool that provides the best conclusion given the available data. ... the math
I am proposing can handle multiple changes to the same file just fine. I added specific
examples [1] as tests so that Greg may see it operate.

... it is the best way to simulate per-changeset coverage without actually doing it. It also
provides us a way to compare coverage over multiple revisions. Again, neither of these
capabilities may be useful, which is why we are putting Marco's coverage mapping (and the
math that can replace it) behind an API [2] the frontend can use.  We can decide later if we
want the features [that the] math provides.

[1] https://github.com/klahnakoski/diff-algebra/blob/master/tests/test.py

DiffViewer - Refactor state structure

Currently we have appError, csetMeta, parsedDiff and we do data manipulations across all modules.
Instead I want to do all coverage and parsedDiff manipulations in DiffViewerContainer, plus store new data. The data structure will be like this:

{
  appError // as -is
  csetMeta // XXX: We will move information from 'coverage' into 'files'
  files: {
    filePath: {
       // The next two are to determine which files score worst and sort by it
      addedLines,
      coveredLines,
      folded, // To support folding files
    }
  }
}

Do not color removed lines

The diff viewer should not give any color to the removed lines because they are not important for determining coverage. Maybe the removed lines should not even be shown; instead showing only the new hunks and coloring the based on if they are covered, or not

Show 0/0 lines as 100%

This will help RelMan when viewing the main page of changesets; they are only interested in low coverage. 0/0 does not fit their definition of low coverage

DiffViewer - Lines with no coverage information are marked as miss

This cset [1] has a bug at the end of the page.
There's 4 lines added.
The coverage data [2] only has data for 2 lines.
I was expecting another 2 lines with '?'

@marco-c is this a bug in the backend? or should I mark lines w/o coverage as white?

[1] https://firefox-code-coverage.herokuapp.com/#/changeset/c56352d90f678c2ad104da657aae116513502153
[2] https://uplift.shipit.staging.mozilla-releng.net/coverage/changeset/c56352d90f678c2ad104da657aae116513502153

    {
      "changes": [
        {
          "coverage": "Y",
          "line": 170
        },
        {
          "coverage": "Y",
          "line": 385
        }
      ],
      "name": "layout/build/nsLayoutStatics.cpp"
    },

image

ChangesetsViewer - Allow filtering changesets by description

@marco-c CC

First of all, this is a non-trivial amount of work.

The easiest implementation would be to simply collapse changesets associated to 1 bug yet still be able to show each individually and reach the diff viewer for each changeset.

A perfect example of which cases would be benefit the most from this work would be a push like the one in the screenshot below (15+ changesets associated to 1 bug).

I'm not planning to tackle this, however, I'm open to mentor anyone interested on this project.

image

Normalized state for FileViewerContainer

A lot of data manipulations happen at the lower components rather than at the top component.

Here's a comment from the PR (paraphrased):

Calculate all of this information at the top level component where the data is fetched.
Create a data structure like this (There might more data needed for each line):

this.state = {
   selectedLine: 0,
   lines: {
     0: {
       testList: getTestList(coverage.testsPerHitLine[lineNumber],
     }
   }
   allTests: getTestList(coverage.allTests),
}

That way all data processing happens in a single place and each piece in the top state has a direct influence on the UI. Your UI is a representation of your state.

No more data manipulations at the low level sub-components.

Also, these changes make it very easy to access all significant data of a line anywhere in the app like this this.state.lines[lineNumber].testList or this.state.allTests.

Diff viewer improvements

  • metadata
  • list of files with links to the divs
  • collapsible divs
  • linkable lines
  • receive changeset parameter to display and load on the fly
  • when loading a raw-diff show a spinner (since fetching takes long)
  • when a diff gets loaded once see if we can cache it (probably with react-redux)
  • remove new line if value of old one is the same
  • receive changeset parameter to display and load on the fly

Reduce number of pushes in the list view

Loading the page now:

Push date Author Changeset Description Collapsed csets Coverage summary
28/9/2017, 11:44:43 Sebastian Hengst <arch 76a26ef7c493 merge mozilla-inbound to mozilla-central 8 changesets in push - [Expand]  
28/9/2017, 11:42:39 Henrik Skupin <mail@hs 82c2eecf82ba Bug 1403616 - Defer logging of Marionett 68 changesets in push - [Expand]  
28/9/2017, 01:52:56 Wes Kocher <wkocher@mo 5ebe2e8980c6 Merge inbound to m-c a=merge CLOSED TREE 62 changesets in push - [Expand] Failed to fetch.
27/9/2017, 23:55:32 Sebastian Hengst <arch 69e3f8981645 merge autoland to mozilla-central. r=mer 109 changesets in push - [Expand] Failed to fetch.
27/9/2017, 19:22:29 David Major <dmajor@mo 6100472d3aa8 Bug 1403220 - De-optimize some font func    
27/9/2017, 11:48:13 Sebastian Hengst <arch 35fbf14b96a6 merge mozilla-inbound to mozilla-central 35 changesets in push - [Expand]  
27/9/2017, 11:46:12 gasolin <gasolin@gmail 5563e7da39b2 Bug 1399536 - fix incorrect JS in test-o 33 changesets in push - [Expand]  
27/9/2017, 02:11:27 Wes Kocher <wkocher@mo 70158e4e215d Merge autoland to central, a=merge MozR 75 changesets in push - [Expand]  

There are a total of 391 changesets. This is likely too many changesets, users will not be able to look at all of them.

Add docs about coverage

Add this information to the docs.

The added lines which are not covered are either:

  • not instrumented because they are not executable (e.g. a comment, or a variable declaration);
  • not instrumented because they are optimized out by the compiler;
  • belong to files for which we don't collect coverage (e.g. Python files, INI files, and so on);
  • a bug somewhere in the instrumentation or the parsing of the results.

The first case is not actually a problem (the line is not executable at all, so we shouldn't consider it for coverage measurement purposes).
The second case can be a problem if it happens often (it would be interesting to compare a coverage report coming from a build without optimizations with a coverage report coming from a normal build).
The third case is not actually a problem, but to avoid noise perhaps we can collapse by default the hunks that modify files for which we don't collect coverage.
The fourth case hopefully never happens, but we can't know for sure.

DiffViewer - Reshuffle some links

Move "GitHub", "Codecov" and "Coverage backend" links to the bottom of the page and make them very small.
They're only useful for contributors of this app when debugging.

Add Flow typing

There is propTypes but I'm going to try Flow.
The fx team is moving to it.

I've wasted half a day because I was trying to use a variable that was not defined.
The error in the console was TypeError: Function.prototype.bind.apply(...) is not a constructor

New and covered percent may be wrong

Calculating new_lines_covered/total_new_lines may be wrong: The new lines may not be on executable files, so should not be part of the count. The UI should intersect the new lines of the changeset with the uncovered lines from the coverage to get uncovered_new_lines, which then can be used to calculate the percent new lines covered.

Add file viewer

CC: @LinkaiQi @klahnakoski @armenzg

This viewer would show the coverage, from multiple tests, for a given file, at a given revision.

The user should be able to interact with the UI to know what test covered what lines.

Based on discussions with Kyle,

There is a drawing of this idea in the docs directory.

Diff view with sample code coverage data

The current JSON agreed metadata will look like this:

    {
      "child_coverage_revision": <Newer-Coverage-Revision>,
      "parent_coverage_revision": <Older-Coverage-Revision>,
      [
        {  // Source file 1
          "name": <Source-file-name>,
          // "extra": { .. },     // extra information if we ever need some. Will only be added once we start needing it.
          "changes": [      // changes broken down by hunk
              {  // Hunk 1
                "old-start, old-length, new-start, new-length": // This is the field that is shown in hg as "@@ old_line_start, old_length, new_line_start, new_length @@", we can just store the entire string
                "lines": [
                  (Coverage:true/false, Line_type: any("+", "-", ""), Old_line, New_line, Content), // Where 'any' signifies that either of those string options can be given.
                  ...
                ]
              },
              {  // Hunk 2
                ...
              }
          ]
        },
        ...
        {  // Source file 2
           ...
        }
      ]
    }

Add "Loading..." functionality

Sometimes it would be nice to know that the UI is just waiting for data to load.
This can easily be accomplished by returning a string ("Loading...") when the components first load before the fetch requests have completed.

parse-diff fails with certain diffs

This servo diff makes the parser fail.

I'm thinking of switching to this package (since it is more actively maintained) and see if it gets fixed.

The full error can be seen on a development environment:
http://localhost:5000/#/changeset/112dba6948d388a6154f073c4f09c2c6a9addcf7

Uncaught (in promise) Error: Objects are not valid as a React child (found: TypeError: Cannot read property 'changes' of null). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of `DiffViewerMeta`.
    at invariant (invariant.js:44)
    at traverseAllChildrenImpl (traverseAllChildren.js:144)
    at traverseAllChildren (traverseAllChildren.js:172)
    at flattenChildren (flattenChildren.js:66)
    at ReactDOMComponent._reconcilerUpdateChildren (ReactMultiChild.js:202)
    at ReactDOMComponent._updateChildren (ReactMultiChild.js:310)
    at ReactDOMComponent.updateChildren (ReactMultiChild.js:297)
    at ReactDOMComponent._updateDOMChildren (ReactDOMComponent.js:942)
    at ReactDOMComponent.updateComponent (ReactDOMComponent.js:760)
    at ReactDOMComponent.receiveComponent (ReactDOMComponent.js:722)

DiffViewer - Add link to Bugzilla

I'd like to have a link on the top of the page to bugzilla with correct bug number to add a pre-filled comment with coverage numbers.

Don't show merges in the list view

These commits contain hundreds of changes, it's difficult for a user to understand which change is being introduced by which patch and so it's difficult to blame a single patch for introducing uncovered code.

Manual test plan

Once we're satisfied with the product we should verify the following changesets:

  • Rust diff
    • Since we don't support Rust we should see a diff without highligting

Increase size of filename

The filenames of the diff viewer are too small, make it bigger. so it overwhelms the less relevant "@@" chunk markers.

Commit history

List of commits. Linking to diff viewers.

To do:

  • fetch hg web data and display changesets
  • description
  • remove ffxbld from list of commits (2017-09-05)
  • showing tipmost changeset of a push rather that oldest (2017-09-05)
  • link to code coverage diff viewer
  • show commits contained between commits
  • allow hidding commits contained within each push

Add coverage summary for each changeset

CC: @marco-c

We currently only add the summary for the tipmost changeset of a push.

We would like to do the following instead:

  • Once we know that a push has coverage data do a parallel fetch for every changeset in push
    • except for merges which should not be shown anyway
  • Show a summary like this (more compact & to be discussed):
New lines coverage change: 100% - Added lines: 1 / Covered lines: 1

refactor - Have unified state management

if I open a link from the main page and go back in using the left arrow, then I need to wait 10 seconds to get the main page...

This is due that each view was designed as different apps with their own separate state.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.