0

If anyone knows how to fix the error or errors that could appear from the code below that would be nice.

I based the code on this code pytest request param of fixture to be used in tests

I am getting an error ERROR - TypeError: fixture() got an unexpected keyword argument 'username_or_email_form'

https://flask.palletsprojects.com/en/2.3.x/testing/

If you want to create the configurations you can do something like this in conftest.py

@pytest.fixture()
def app():
    app = create_app()
    app.config.update({
        "TESTING": True,
        "MAIL_SUPRESS_SEND" = True  
        "SECRET_KEY" = 'temp_secret_key' 
        "SQLALCHEMY_TRACK_MODIFICATIONS" = False
        "SQLALCHEMY_DATABASE_URI" = os.environ.get('DATABASE_URI') or 
        'sqlite:///' + os.path.join(basedir_for_database, 'app.db')    
    })
    yield app

tests/models.py



class UserTest(UserMixin, db.Model):
    __bind_key__ = "testing_app_db"
    __tablename__ = 'usertest'
    id = db.Column(db.Integer, primary_key=True)
    #  unique blocks the same usernames
    # I can't have Nullable=False because it will make me add the columns everytime I add a column in User table
    username = db.Column(db.String(80), unique=True)
    hashed_password = db.Column(db.String(128))
    email = db.Column(db.String(120), unique=True)
    registration_confirmation_email = db.Column(db.Boolean, default=False) 
    # need a better backref name.
    paymentstest = db.relationship('PaymentsTest', backref='profileinfo', lazy=True) 
  


    def __repr__(self):
        return f"UserTest('{self.username}', '{self.hashed_password}', '{self.email}')" 
 


tests/login_test/conftest.py

from app.config import PytestConfig 
import pytest, bcrypt, os  



test_app = create_app(PytestConfig) 
from ..models import UserTest, db
db

@pytest.fixture
def username_form():
    '''This username_form_form is for pytest'''
    
    username = 'fkpr[kfkuh'
    return username

@pytest.fixture 
def plaintext_password_form():   
   '''This plaintext_password_form_form is for pytest'''  
   
   plaintext_password = 'pojkp[kjpj[pj'
   return plaintext_password

@pytest.fixture
def hashed_password_form():    
    '''This hashed_password_form is for pytest'''
   
    plaintext_password = 'pojkp[kjpj[pj'
    # converting password to array of bytes
    bytes = plaintext_password.encode('utf-8')
    # generating the salt
    salt = bcrypt.gensalt()
    # Hashing the password
    hashed_password_form = bcrypt.hashpw(bytes, salt)
    return hashed_password_form



@pytest.fixture 
def email_form(): 
    '''This email_form is for pytest'''
    '''For both UserTest and Payments'''
    email_form = os.environ['TESTING_EMAIL_USERNAME']
    return email_form 


@pytest.fixture
def item_name_form():
    '''This item_name_form is for pytest'''
    item_name_form = 'donation'  
    return item_name_form



@pytest.fixture
def price_of_donation_form():    
    '''This price_of_donation_form is for pytest'''
    # equal to 66 cents
    price_of_donation_form = 66
    return price_of_donation_form





class conftests_class():


    @pytest.fixture(scope="class", username_or_email_form=[username_form, email_form])
    def req_param(self, request):
        return request.username_or_email_form
    
  

    @pytest.fixture
    def seperate_username_or_email_form(self, req_param):
      
        '''
        seperates the username and email and outputs a value from the User table.
        This is in the /login route
        '''
        
        
        username_or_email_form = req_param
   
        if UserTest.query.filter_by(username=username_or_email_form).first(): 
            username_db = UserTest.query.filter_by(username=username_or_email_form).first()
            if username_db.username == username_or_email_form:
                user_db = email_db
                print('Success the username is returned.') 
                return user_db.username
                
        elif email_db:
            email_db = UserTest.query.filter_by(email=username_or_email_form).first()
            if email_db.email == username_or_email_form:
                user_db = email_db
                print('Success the email is returned.') 
                return user_db.email
        else:
            print('username or email do not exist')




@staticmethod
@pytest.fixture
def yield_username_or_email_db():  
    
    '''
    Create the db column then yield the selected/queried usertest and finally delete the db.
    yield does not stop the code when yielded.
    '''
    
    # = with app.app_context() except won't work for pytest
    with test_app.test_request_context():

        bind_key="testing_app_db"
  
        def _subfunction(req_param, seperate_username_or_email_form, username_form, hashed_password_form, email_form):
                        
            db.create_all(bind_key)
            usertest_db = UserTest(username=username_form, hashed_password=hashed_password_form, email=email_form)
            db.session.add(usertest_db)
            db.session.commit()
               
           
            # returns the username or email form from a db query.
            seperate_username_or_email_form = seperate_username_or_email_form(req_param)


                # yield unlike return doesn't stop when called.
            yield _subfunction 
            db.drop_all(bind_key) 

tests/login_test/test_login_functions.py

 # if the username or email do not exist then you do not login and redirected
# Don't check for password because people can have the same password

def test_True_Output_check_if_username_is_in_db(self, req_param, seperate_username_or_email_form, username_form, hashed_password_form, email_form):
    '''
    if the username or email is in the db the code works,
    if not it redirects.

    This runs in the /login route.
    username_form is in the database.
    The if statement checks if the query is empty/has no values in db.
    The if statement query will be False because it has a db value.  
    The output in the fixture is True. 
    '''

    username_or_email_db = (req_param, seperate_username_or_email_form, username_form, hashed_password_form, email_form)
    # makes it so db will run if empty list []
    if not UserTest.query.filter_by(username=username_or_email_db).first():
        print("return False, The username does not exist or you mistyped the username. Please fill out the correct username.")     
        # redirects to the auth.login route in non pytest code instead of False

        # extra code for pytest!!
        # This should not reach the assert
        assert UserTest.query.filter_by(username=username_or_email_db).first() != username_or_email_db
    
    # makes it so db will run if empty list []
    elif not UserTest.query.filter_by(email=username_or_email_db).first():
        print("return False, The email does not exist or you mistyped the email. Please fill out the correct username.")     
        # redirects to the auth.login route in non pytest code instead of False
    
        # extra code for pytest!!
        # This should not reach the assert
        assert UserTest.query.filter_by(username=username_or_email_db).first() != username_or_email_db
    # extra code for pytest!!
    else:
        # Both values should be equal
        assert UserTest.query.filter_by(username=username_or_email_db).first() == username_or_email_db , 'The username or email do not exist'
        print(' True username or email exist')

This is why I want to this unless someone has a better idea.

trewbth
  • 13
  • 5
  • The argument to `pytest.fixture` is always called `params`. The function will be called several times, with `request.param` having the value of each entry in the `params` list. – Tim Roberts Jul 08 '23 at 03:04
  • @TimRoberts Thanks for the help. I changed the main arguments to params. The error disappeared but the assert statement in `test_True_Output_check_if_username_is_in_db` in the else statement doesn't work. I changed the assert `assert UserTest.query.filter_by(username=username_or_email_db).first() == username_or_email_db` to assert UserTest.query.filter_by(username=username_or_email_db).first() != username_or_email_db` and neither assert or assertion error shows. Any advice? – trewbth Jul 08 '23 at 05:57
  • You're in the debugging phase. You'll need to print some intermediate values to see what the tester is delivering. – Tim Roberts Jul 08 '23 at 06:55
  • @TimRoberts In the code below when I run pytest -q --capture=no and I got rid of conftest.py and just moved all the code to tests/login_test/test_login_functions.py https://hastebin.com/share/hulihemuhu.python Nothing prints. Any advice? – trewbth Jul 08 '23 at 22:41
  • Here is a link for some reason the link above is not working https://pastebin.com/7n9HUeyv – trewbth Jul 08 '23 at 22:48

0 Answers0