truth table: Binary Operations I


requirements

how to make a python test driven development environment with truth_table as the name of the project

There are 16 binary operations, they all take 2 inputs, each of the inputs can be True or False, which gives four cases


test_contradiction

red: make it fail

I add a new TestCase to test_truth_table.py

    def test_logical_negation_aka_not(self):
        ...


class TestBinaryOperations(unittest.TestCase):

    def test_contradiction(self):
        self.assertFalse(src.truth_table.contradiction(True, True))

the terminal shows AttributeError

AttributeError: module 'src.truth_table' has no attribute 'contradiction'

green: make it pass

I add a function definition to truth_table.py

def logical_negation(argument):
    return not argument


def contradiction(argument):
    return not argument

the terminal shows TypeError

TypeError: contradiction() takes 1 positional argument but 2 were given

I change the signature to make it take 2 inputs

def contradiction(p, q):
    return not p

the test passes

refactor: make it better

  • I add the second case

    def test_contradiction(self):
        self.assertFalse(src.truth_table.contradiction(True, True))
        self.assertFalse(src.truth_table.contradiction(True, False))
    

    the test is still green.

  • I add the next case

    def test_contradiction(self):
        self.assertFalse(src.truth_table.contradiction(True, True))
        self.assertFalse(src.truth_table.contradiction(True, False))
        self.assertFalse(src.truth_table.contradiction(False, True))
    

    the terminal shows AssertionError

    AssertionError: True is not false
    

    all three cases of the test expect False. I change the return statement

    def contradiction(p, q):
        return False
    

    the test is green again

  • I add the fourth case

    def test_contradiction(self):
        self.assertFalse(src.truth_table.contradiction(True, True))
        self.assertFalse(src.truth_table.contradiction(True, False))
        self.assertFalse(src.truth_table.contradiction(False, True))
        self.assertFalse(src.truth_table.contradiction(False, False))
    

    another case that expects False, the test is still green! contradiction always returns False


test_logical_conjunction

red: make it fail

I add the next test

def test_contradiction(self):
    ...

def test_logical_conjunction(self):
    self.assertTrue(src.truth_table.logical_conjunction(True, True))

the terminal shows AttributeError

AttributeError: module 'src.truth_table' has no attribute 'logical_conjunction'. Did you mean: 'logical_negation'?

green: make it pass

I add the function

def contradiction(p, q):
    return False


def logical_conjunction(p, q):
    return True

the test passes

refactor: make it better

  • I add the next case

    def test_logical_conjunction(self):
        self.assertTrue(src.truth_table.logical_conjunction(True, True))
        self.assertFalse(src.truth_table.logical_conjunction(True, False))
    

    the terminal shows AssertionError

    AssertionError: True is not false
    

    when I add a return statement for False

    def logical_conjunction(p, q):
        return False
        return True
    

    the terminal shows AssertionError

    AssertionError: False is not true
    

    for the line that was passing before. logical_conjunction has to choose whether to return False or True based on the inputs. I can make it do that with if statements

    def logical_conjunction(p, q):
        if p == True:
            if q == False:
                return False
        return True
    

    the test passes. The function returns False when p is True and q is False, otherwise it returns True by default

  • I add the next case

    def test_logical_conjunction(self):
        self.assertTrue(src.truth_table.logical_conjunction(True, True))
        self.assertFalse(src.truth_table.logical_conjunction(True, False))
        self.assertFalse(src.truth_table.logical_conjunction(False, True))
    

    and get AssertionError

    AssertionError: True is not false
    

    I add another if statement

    def logical_conjunction(p, q):
        if p == False:
            if q == True:
                return False
        if p == True:
            if q == False:
                return False
        return True
    

    the test passes

  • I add the last case

    def test_logical_conjunction(self):
        self.assertTrue(src.truth_table.logical_conjunction(True, True))
        self.assertFalse(src.truth_table.logical_conjunction(True, False))
        self.assertFalse(src.truth_table.logical_conjunction(False, True))
        self.assertFalse(src.truth_table.logical_conjunction(False, False))
    

    the terminal shows AssertionError

    AssertionError: True is not false
    

    I add an if statement for it

    def logical_conjunction(p, q):
        if p == False:
            if q == False:
                return False
            if q == True:
                return False
        if p == True:
            if q == False:
                return False
        return True
    

    the terminal shows green

  • I add an if statement for the first case to make it clearer

    def logical_conjunction(p, q):
        if p == False:
            if q == False:
                return False
            if q == True:
                return False
        if p == True:
            if q == False:
                return False
            if q == True:
                return True
    
  • There are only 2 results for this operation, in the first case the function returns True and in the other 3 cases it returns False. I rewrite the if statement for the case where the result is True then use an else clause for the other cases

    def logical_conjunction(p, q):
        if p == True and q == True:
            return True
        else:
            return False
        if p == False:
            if q == False:
                return False
            if q == True:
                return False
        if p == True:
            if q == False:
                return False
            if q == True:
                return True
    

    the test is still green. I remove the other if statements then change the first statement with bool

    def logical_conjunction(p, q):
        if bool(p) and bool(q):
        # if p == True and q == True:
            return True
        else:
            return False
    

    still green. bool(x) checks if x is True. I remove the commented line and rewrite the first line to make it simpler

    def logical_conjunction(p, q):
        if p and q:
        # if bool(p) and bool(q):
            return True
        else:
            return False
    

    the test is still green, Python tests if p and q are True in the background, I remove the commented line

  • Python has ternary operators or conditional expressions which allow me to write the if statements as one line

    def logical_conjunction(p, q):
        return True if p and q else False
        if p and q:
            return True
        else:
            return False
    

    the terminal shows green, I remove the other if statements and rewrite the return statement in an even simpler way thanks to Python’s truth value testing

    def logical_conjunction(p, q):
        return p and q
        return True if p and q else False
    

    still green! I remove the second return statement

    def logical_conjunction(p, q):
        return p and q
    

test_project_second

red: make it fail

I add another test

def test_logical_conjunction(self):
    ...

def test_project_second(self):
    self.assertTrue(src.truth_table.project_second(True, True))

the terminal shows AttributeError

AttributeError: module 'src.truth_table' has no attribute 'project_second'

green: make it pass

When I add a function definition for it

def logical_conjunction(p, q):
    return p and q


def project_second(p, q):
    return True

the test passes

refactor: make it better

  • I add the second case

    def test_project_second(self):
        self.assertTrue(src.truth_table.project_second(True, True))
        self.assertFalse(src.truth_table.project_second(True, False))
    

    the terminal shows AssertionError

    AssertionError: True is not false
    

    I add an if statement

    def project_second(p, q):
        if p == True:
            if q == False:
                return False
        return True
    

    the test passes

  • I add the next case

    def test_project_second(self):
        self.assertTrue(src.truth_table.project_second(True, True))
        self.assertFalse(src.truth_table.project_second(True, False))
        self.assertTrue(src.truth_table.project_second(False, True))
    

    the test is still green

  • I add the last case

    def test_project_second(self):
        self.assertTrue(src.truth_table.project_second(True, True))
        self.assertFalse(src.truth_table.project_second(True, False))
        self.assertTrue(src.truth_table.project_second(False, True))
        self.assertFalse(src.truth_table.project_second(False, False))
    

    and the terminal shows AssertionError

    AssertionError: True is not false
    

    I add another if statement

    def project_second(p, q):
        if p == False:
            if q == False:
                return False
        if p == True:
            if q == False:
                return False
        return True
    

    the test passes

  • This function returns True when q is True and returns False when q is False. I add a new statement to show this

    def project_second(p, q):
        return q
        if p == False:
            if q == False:
                return False
        if p == True:
            if q == False:
                return False
        return True
    

    the test is still green, I remove the other statements

    def project_second(p, q):
        return q
    

test_converse_non_implication

red: make it fail

I add another test

def test_project_second(self):
    ...

def test_converse_non_implication(self):
    self.assertFalse(src.truth_table.converse_non_implication(True, True))

the terminal shows AttributeError

AttributeError: module 'src.truth_table' has no attribute 'converse_non_implication'

green: make it pass

I add the function

def project_second(p, q):
    return q


def converse_non_implication(p, q):
    return False

the test passes

refactor: make it better

  • I add another case

    def test_converse_non_implication(self):
        self.assertFalse(src.truth_table.converse_non_implication(True, True))
        self.assertFalse(src.truth_table.converse_non_implication(True, False))
    

    the test is still green

  • I add the third case

    def test_converse_non_implication(self):
        self.assertFalse(src.truth_table.converse_non_implication(True, True))
        self.assertFalse(src.truth_table.converse_non_implication(True, False))
        self.assertTrue(src.truth_table.converse_non_implication(False, True))
    

    the terminal shows AssertionError

    AssertionError: False is not true
    

    I add an if statement

    def converse_non_implication(p, q):
        if p == False:
            if q == True:
                return True
        return False
    

    the test is green again

  • I add the next case

    def test_converse_non_implication(self):
        self.assertFalse(src.truth_table.converse_non_implication(True, True))
        self.assertFalse(src.truth_table.converse_non_implication(True, False))
        self.assertTrue(src.truth_table.converse_non_implication(False, True))
        self.assertFalse(src.truth_table.converse_non_implication(False, False))
    

    the terminal still shows green

  • I can put the two if statements together with and

    def converse_non_implication(p, q):
        if p == False and q == True:
        # if p == False:
        #    if q == True:
                return True
        return False
    

    the terminal still shows green. I remove the other statements and rewrite the first line with logical negation and bool

    def converse_non_implication(p, q):
        if not p == True and bool(q):
        # if p == False and q == True:
            return True
        else:
            return False
    

    still green. I remove the comment and rewrite the line again

    def converse_non_implication(p, q):
        if not bool(p) and q:
        # if not p == True and bool(q):
            return True
        else:
            return False
    

    the test is still green. I remove the commented line and make the line simpler

    def converse_non_implication(p, q):
        if not p and q:
        # if not bool(p) and q:
            return True
        else:
            return False
    

    the test is still green. I use a conditional expression

    def converse_non_implication(p, q):
        return True if not p and q else False
        if not p and q:
            return True
        else:
            return False
    

    still green. I use the simpler return statement

    def converse_non_implication(p, q):
        return not p and q
        return True if not p and q else False
    

    all tests are still passing. I remove the second return statement

    def converse_non_implication(p, q):
        return not p and q
    

review

Binary Operations take 2 inputs which could be True or False, if we name the first input p and the second q, the tests show that

do you want to test more binary operations?


truth table: tests and solutions