1

I am using a variable to define the ROOT_DIR in my .gitlab-ci.yml

variables:
  ROOT_DIR: "/builds/company/projects/projectname/"

in the job I call the test.py function:

ut-job:
  stage: test
  script:
    - echo "Unit testing ..."
    - python3 tests/test_file.py "$ROOT_DIR"

In the test_file.py I call the command line inout as follows:

if __name__ == "__main__":
    if sys.platform == "Darwin" or sys.platform == "Windows":
        load_dotenv()
        ROOT_DIR = os.getenv("ROOT_DIR")
    else:
        ROOT_DIR=sys.argv[1]    
    print("PLatform: " + sys.platform)
    print("ROOT_DIR: " + ROOT_DIR)
    
    unittest.main()

The printstatement in the pipeline output correctly prints the ROOT_DIR, so the sys.argv gets the variable correctly.

However, the pipeline fails with

AttributeError: module '__main__' has no attribute '/builds/company/projects/projectname/'

Meaning, the test_file.py main gets the Variable but somehow tries to use it also as an attribute.

Can somebody hint me what I did wrong?

2 Answers 2

1

The issue here is that when you call unittest.main, it inspects the contents of sys.argv for parameters, in this case, test names. It will try to use provided arguments to get tests to run by using getattr on the current module. In this case, resulting in an attribute error.

For example, suppose you have a test file (t.py) like this:

import unittest

class Foo(unittest.TestCase):
    def test_foo(self):
        ...

class Bar(unittest.TestCase):
    def test_bar(self):
        ...

unittest.main()

Observe the different results when adding arguments to this file:

With no arguments 2 tests run:

$ python3 ./t.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

With the argument Foo only one test (Foo) runs:

$ python3 ./t.py Foo
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

If you provide an argument of a nonexistent test (say, Baz) you'll get an attribute error for the argument passed:

$ python3 ./t.py Baz
E
======================================================================
ERROR: Baz (unittest.loader._FailedTest)
----------------------------------------------------------------------
AttributeError: module '__main__' has no attribute 'Baz'

----------------------------------------------------------------------
Ran 1 test in 0.000s

To resolve this you can either (1) not pass any arguments for your script or (2) modify sys.argv before calling unittest.main

if __name__ == "__main__":
    if sys.platform == "Darwin" or sys.platform == "Windows":
        load_dotenv()
        ROOT_DIR = os.getenv("ROOT_DIR")
    else:
        ROOT_DIR=sys.argv[1]
        sys.argv.pop(1)   # remove rootdir from cli arguments 
    print("PLatform: " + sys.platform)
    print("ROOT_DIR: " + ROOT_DIR)
    
    unittest.main()
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your help. I have an additional question. I noticed that the Variable is actually not used, but the variable set in Settings-> Variable. How could I use the yml set variable, or should I always use the settings Variable option? If so, what is the yml Variable used for in this context? Thanks
0

No need to pass an argument when calling the test_file.py. I believe that is causing the error.

ut-job:
  stage: test
  script:
    - echo "Unit testing ..."
    - python3 tests/test_file.py

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.