Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python tests does not count over make cover #54

Closed
1 of 5 tasks
alanjds opened this issue Aug 21, 2018 · 13 comments
Closed
1 of 5 tasks

Python tests does not count over make cover #54

alanjds opened this issue Aug 21, 2018 · 13 comments

Comments

@alanjds
Copy link

alanjds commented Aug 21, 2018

History:

As said in the discussion starting on google#243 (comment), the Python tests does not count over make cover report.

Personally, this hinders the development speed by forcing people to write tests twice: one for Python (what we want working) and one for Golang (what we need to count on make cover).

The hypothesis is: Lowering the work needed to push code, more code will be pushed by more people.

Lets fix it to speed up the development!

Plan:

  • Change grumpc to be able to produce module_test.go output from Python test files
  • Make the make test to produce module_test.go files from grumpy/testing/*.py files
  • Make the produced module_test.go files to be in such place that counts for coverage
  • Write a change in a runtime .go file. Write a test the for the change in a .py
  • Check that make cover counts the .py covering the .go changed
@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by alanjds
Friday Nov 10, 2017 at 01:34 GMT


@trotterdylan had said that:

Coverage is only calculated from tests within the runtime directory.

and

[is] Just the way go test works, it expects *_test.go files with the package name of that being tested. And then within those files it expects Test* functions. One way to do it would be to generate a module_test.go file with a single TestModule function in there that loads the module and executes it as main.

Then I am trying to make the grumpy/testing/*.py files to generate *_test.go files.

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by alanjds
Friday Nov 10, 2017 at 01:39 GMT


From a Python file containing print 'Hello World!', grumpc does produce this module.go:

package __main__
import πg "grumpy"
var Code *πg.Code
func init() {
        Code = πg.NewCode("<module>", "print_hello.py", nil, 0, func(πF *πg.Frame, _ []*πg.Object) (*πg.Object, *πg.BaseException) {
                var πR *πg.Object; _ = πR
                var πE *πg.BaseException; _ = πE
                var πTemp001 []*πg.Object
                _ = πTemp001
                for ; πF.State() >= 0; πF.PopCheckpoint() {
                        switch πF.State() {
                        case 0:
                        default: panic("unexpected function state")
                        }
                        // line 1: print 'Hello World!'
                        πF.SetLineno(1)
                        πTemp001 = make([]*πg.Object, 1)
                        πTemp001[0] = πg.NewStr("Hello World!").ToObject()
                        if πE = πg.Print(πF, πTemp001, true); πE != nil {
                                continue
                        }
                }
                return nil, πE
        })
        πg.RegisterModule("__main__", Code)
}

I managed to add a flag to grumpc that, for the same Python input, produces:

package __main__
import πg "grumpy"
import πt "testing"
var Code *πg.Code
func init() {
        Code = πg.NewCode("<module>", "print_hello.py", nil, 0, func(πF *πg.Frame, _ []*πg.Object) (*πg.Object, *πg.BaseException) {
                var πR *πg.Object; _ = πR
                var πE *πg.BaseException; _ = πE
                var πTemp001 []*πg.Object
                _ = πTemp001
                for ; πF.State() >= 0; πF.PopCheckpoint() {
                        switch πF.State() {
                        case 0:
                        default: panic("unexpected function state")
                        }
                        // line 1: print 'Hello World!'
                        πF.SetLineno(1)
                        πTemp001 = make([]*πg.Object, 1)
                        πTemp001[0] = πg.NewStr("Hello World!").ToObject()
                        if πE = πg.Print(πF, πTemp001, true); πE != nil {
                                continue
                        }
                }
                return nil, πE
        })
        πg.RegisterModule("__main__", Code)
}
func TestRunCode(t *testing.T) {
        init()
        πg.ImportModule(grumpy.NewRootFrame(), "traceback")
        //πg.ImportModule(grumpy.NewRootFrame(), "__main__")
        πg.RunMain(Code)
}

to be saved as module_test.go

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by alanjds
Friday Nov 10, 2017 at 01:41 GMT


Question: Is this an appropriate Go test to count for coverage, or should something be changed on the output yet?

The plan is to, after producing a reasonable output file, figure where should it be placed and how to put it there.

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by trotterdylan
Monday Nov 20, 2017 at 20:58 GMT


I think it's reasonable to use the Python files in testing/ count toward coverage.

Rather than adding complexity to grumpc, could we make this a standalone utility that takes a module name and generates a _test.go file that can be run for this purpose?

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by alanjds
Tuesday Nov 21, 2017 at 13:41 GMT


@trotterdylan Can this new tool be made later, before the merge?
The plan is to have it working, then do a pass cleaning the mess.

In fact, I am biased towards refactor grumpc to make it cleaner. You are right to worry about putting more stuff on tool composed of +70 lines of main().

Anyway,

  • Do the attached output code seems right as a test file?
  • Where should it live on the /build folder to count over the coverage?

(am I making the right questions, or got totally clueless?)

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by trotterdylan
Wednesday Nov 22, 2017 at 02:07 GMT


Thinking about it a little more, what you really want is to do something similar to grumprun, except instead of generating a main() function, you will generate a TestRunCode() function. Unfortunately the logic is a bit different, because you really want to generate the _test.go file, not build and run a binary. I would write a new tool based on what's in grumprun (except much simpler, because it doesn't need invoke grumpc or the Go toolchain) that outputs something like this:

package foo
import (
	"os"
	"grumpy"
	<other transitive imports here>
)
func TestRunCode(t *testing.T) {
	grumpy.ImportModule(grumpy.NewRootFrame(), "traceback")
	if grumpy.RunMain(Code) != 0 {
		t.Fail()
	}
}

This file would be called foo_test.go and would sit alongside the code generated by grumpc for module foo. This would mean you could run the test like: go test __python__.foo. You can then pass -coverprofile to generate coverage data.

The second part of this is to merge coverage data for all the different sources. In particular, the coverage generated for the grumpy package with the coverage generated by each of the tests in testing/. This will require some work to coverparse to pull all that data together into a single coverage report.

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by alanjds
Friday Nov 24, 2017 at 01:19 GMT


Thanks for pointing to a direction and for saying where the test file will end and how to run it.

I will take a look at the grumpyrun later. Maybe this week, maybe next one.

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by alanjds
Saturday Nov 25, 2017 at 15:56 GMT


I see.

You are suggesting to import the module and run it, instead of pasting all the code inside the test...

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by trotterdylan
Saturday Nov 25, 2017 at 16:21 GMT


Right. Except rather than importing it with ImportModule(), call RunMain() on it so that the module is treated as __main__.

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by alanjds
Saturday Dec 09, 2017 at 22:54 GMT


I am writing the new tool. Just realized that the Code is not described on the test file.

Where does it came from? Is imported from the module.go?

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by trotterdylan
Monday Dec 11, 2017 at 15:48 GMT


In the example I wrote above, Code would come from the foo package that's being tested. In Go, the tests are part of the package under test and can access members of that package.

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Comment by alanjds
Tuesday Dec 12, 2017 at 21:49 GMT


On google#389, the new tool gentest got able to produce *_test.go files.

Aside from formatting and this kind of details, do the tool is producing the right _test.go files on the right places?

If so, the next step would be make test to run the testfiles.

@alanjds
Copy link
Author

alanjds commented Aug 21, 2018

Closed in favor of #55, correctly imported with comments

@alanjds alanjds closed this as completed Aug 21, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant