Professional Précis

Author: (Vital Joseph II)

About the Author

Hello, my name is Vital Joseph, I am a junior here at Allegheny, majoring in computer science. I play on the football team here as well. I am looking forward to collaborating with everyone throughout the semester. I think this class is going to be very helpful for us all even though it might seem like a lot at the start, but I am ready to take on the challenge with you all.

Week 2

SE1

Summary

The contents of Preface went over the meaning of “software engineering” and what distinguished the term from programming, computer science, etc. Also how it compared to other terms that had “engineering” in it. Programming Over Time introduces the aspect of software engineering that deals with time. As a software engineer you want to program tools and software that stays valuable over a period of time.

Reflection

Reading through SE1 I got a better understanding of the term “software engineering” and what the goal of a software engineer’s work should always encompass, which is longevity really. Through time, code and programs tend to become less sustainable and harder to use and understand. It is the software engineer’s job to make software that is able to adapt and change over time, not just in the present.

Use-Case

To relate the readings to the chasten project, I believe our goal as a team is to make sure the tools we implement into chasten are not only bug free, but susceptible to a wide variety of patterns. The program uses expressions to find patterns in python program, so it would be more sustainable to recognize as many patterns as possible.

FB1

Summary

The contents of FB1 go into detail about software testing and how important it is to software. Examples of simple function testing are provided, as well as test execution, test generating, and test checking. An example of an automated test used in the read can be seen below.

import bookutils

from Timer import Timer

with Timer() as t:
    for n in range(1, 10000):
        assertEquals(my_sqrt(n) * my_sqrt(n), n)
print(t.elapsed_time())

As you can see in the example above, assertEquals is used, which is a statement that checks if two values are equal. If true then nothing happens, but if false then an exception is raised, meaning a failed test. You can also see the Timer module is imported, allowing us to record the runtime of the test, which in this case is the output would be 0.0336528339976212.

Reflection

Testing is a vital part of software engineering, testing helps identify bugs and locate bugs in programs that can cause crashes. Testing also helps is also a way to validate your code and shows that the user’s needs are met. It can help miminimze risk later on in projects as well by pointing out bugs early on so that they dont come up later in the develpment process.

Use-Case

Making test is something that we will have to do in our develpment process of chasten. I think a group of people who are good at making test cases should be are so called bug finders. That way we could have multiple hands on different implementations instead of one person making their own test case for their own implementation. This would result in more bug-free code in my opinion.

Week 3

SE2

Summary

What is Software Engineering dives into the aspects of software engineering and the approach that google uses to have a sustainable codebase. The text goes into to detail how software engineering and programming are not the same. A lot of the difference is seen in the management of code over time, the scale and efficiency, and the decision making of the trade-offs and costs.

Reflection

Reading the contents of SE2, I understand software engineering in a different light. I always though of software engineering as just programming and never reealised there is much more to it. Programming is a vital part to software engineering but it certainly isnt all software engineering is. Now when I think of software engineering, I think of not only programming but modifcation, maintenece, testing, documentaion, etc. All areas that that are just as important as the development process of a program.

Use-Case

Through the develpoment process of chasten we need to make sure that we need stay on top of our maintnence an documentation for chasten to be sutainable. We are starting to get more comfortbale with adressing issues and assigning people to fix said issues as well as documenting any uncertaincies or problems we might come across. As long as we continue to improve as a collective we should be succsessful.

FB2

Summary

This chapter of fuzzing book talks covers the coverage of code, which is the measurement of which parts of a program are actually executed during a test run. Code coverage tools can also show which parts of code have remained untested. Some types of code coverage mentioned in this chapter include line coverage, branh coverage, and statement coverage. Line covergage being a tool or metric that shows which lines of code were touched when running tests. Line coverage uses the trace method, which returns a list of lines executed in order. An example of line coverage can be seen below:

>>> cov.coverage()
{('cgi_decode', 8),
 ('cgi_decode', 9),
 ('cgi_decode', 10),
 ('cgi_decode', 11),
 ('cgi_decode', 12),
 ('cgi_decode', 15),
 ('cgi_decode', 16),
 ('cgi_decode', 17),
 ('cgi_decode', 18),
 ('cgi_decode', 19),
 ('cgi_decode', 20),
 ('cgi_decode', 21),
 ('cgi_decode', 30),
 ('cgi_decode', 31),
 ('cgi_decode', 32)}

as you can see, the coverage method produces lines of code from the trace method that have executed at least once. Branch coverage is also important because it measure branches in code, which are the if statment and loops. Statement coverageis just a more fined tuned metric of line coverage because it measure each stement of code.

Reflection

Coverage is important in a program because it shows which parts of the code have been covered by tests and which parts remain untested. It isnt necessarily a test itself though and that was what I had to get my head wrapped around while reading. It simply helps with code testing my providing vital information that can be used to show that a test might need to be improved.

Use-Case

For the development of chasten, code coverage will be important for people working on test cases. It will show whether our test cases are efficient or not. Line and Branch coverage are probably going to be the most common and simple to implement. It might be tidious, but it will help ensure our test or testing the right code and help with sustainability.

Week 4

SE3

Summary

Reading the chapter of SE3, “How to Work Well on Teams”, I found that the authors wanted to explain the importance of working with other people in software engineering and how to succeed in a engineering team. You have to evaluate yourself as a colleuge and make sure you have the basic foundation pillars you need to work with other people. Those pillars stem around humilty, trust, and respect.

Reflection

Reading this chapter I self reflected on myself as a member of a working team and asked myself questions about the three pillars of social interaction. 1. Am I afraid of people seeing that I am not familiar with ceartain technical skills? 2. Do I provide assistance when needed and do I seek assistance? Do I have trust that we will implement and fix the necessary tools for oour project? These questions I feel if answered truthfully will give insight on where you are at as a team player.

Use-Case

As we work with chasten, we have to make sure that we voice our uncertaincies or disapprovements to everyone. It is important that everyone is heard and feels like they have a voive in the matter. We are lso in a class where different people hast different levels of technical skills, It is our duty to assist in areas where we feel like we are technically advanced or at least have a firm idea of what to do and how to do it. The more we grow as a team, technically, the faster the development process will move along. The aim of this course is not meant for certain people with more expertise to carry the load, everyone should come out of the course with the same understanding of how our software works.

FB3

Summary

In the “fuzzing” chapter of fuzzingbook, the main topic is fuzzing also known as random text generation. Which is the randomization of characters based on certain constraint into a string. In the chapter a simple fuzzer function is ran:

def fuzzer(max_length: int = 100, char_start: int = 32, char_range: int = 32) -> str:
    """A string of up to `max_length` characters
       in the range [`char_start`, `char_start` + `char_range`)"""
    string_length = random.randrange(0, max_length + 1)
    out = ""
    for i in range(0, string_length):
        out += chr(random.randrange(char_start, char_start + char_range))
    return out

As you can see the fuzzer function takes in a max length which defaults to 100, this is how many charcaters are in the string. Then we have char start and range which is used in chr function towards the end of the function. This just gives a range of how many different ASCII codes are used iin the string. If all is correct then you should get a output looking like this.

'!7#%"*#0=)$;%6*;>638:*>80"=</>(/*:-(2<4 !:5*6856&?""11<7+%<%7,4.8,*+&,,$,."'

A string full of random generated characters.

Reflection

Reading through the chapter I got a better understanding of the importance of fuzzing and how it played in testing mostly. Fuzzing can help identify bugs and vulnerabilities in code because it examplifies user-generated datac and not fixed inputs. This will show how well a program can handle diverse inputs.

Use-Case

While working on chasten it will be important to implement fuzzing testing technique to simulate user behaviour because the goal is for chasten to be a user friendly software that students and faculty can use everyday.

Week 5

SE4

Summary

The chapter’s “Knowledge Sharing” in SE main topic is organization. What is an organization in software engineering. Basically, a group of engineers and developers that come together to create and maintain software. Just like any team, there are challenges that you have to overcome to be successful in your project or end goal. Software orgranizations sometimes have problems creating cultures of learning where people are not afraid to share their lack of knowledge to gain knowledge from others. You have to give a little to get a little.

Reflection

Reading the chapter I reflected on what it takes to develop a environment where learning is the norm. You have to make sure that you, as someone that maybe has a lack of knowledge is a cerain area, communicate with others to and let it be known that you are seeking help. As well as the person that has a expetise in an area. For one, it is important that you branch out of area that your familiar with and challenge yourself as a software enginneer. It is also important that you help others and share your knowledge if ypu are furhter along in an area or further along in solving an issue.

Use-Case

During the development process of chasten I think that as a class we are starting to get the ball running with just overall knowledge of the tools in chasten and how they work, but I think that some people are further along as others and it is important that they realize that and try and share their knowledge in instances. It is also important to work on diverse issues when choosing which ones you want to resolve, there are issue that work with source code as well as documentation.

FB4

Summary

This chapter of fuzzingbook covers mutation analysis, which is another testing technique used to evaluate the effectiveness of a set of test cases. This testing technique measures the ability to detect changes or mutations in the source code of functions. The book uses the vocabulary “artificial faults” as changes to function. Here is an example:

def triangle_m1(a, b, c):
    if a == b:
        if b == c:
            return 'Equilateral'
        else:
            # return 'Isosceles'
            return None  # <-- injected fault
    else:
        if b == c:
            return "Isosceles"
        else:
            if a == c:
                return "Isosceles"
            else:
                return "Scalene"

As you can see a change has been made in the function. And a test case is used to detect any changes:

with ExpectError():
    strong_oracle(triangle_m1)

This is the output:

Traceback (most recent call last):
  File "/var/folders/xx/h9_h9csd3_9f81t89rrf1qr00000gn/T/ipykernel_15695/3191755624.py", line 2, in <module>
    strong_oracle(triangle_m1)
  File "/var/folders/xx/h9_h9csd3_9f81t89rrf1qr00000gn/T/ipykernel_15695/566939880.py", line 5, in strong_oracle
    assert fn(2, 2, 1) == 'Isosceles'
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError (expected)

The test case detected the mutation and produced and Error because it was expecting Isosceles instead of None.

Reflection

When looking at the strong_oracle and weak_oracle functions I was finding it hard to distinguish why one produced an error and one did not at first, but then I took a closer look at the weak_oracle function and saw that it used the did not equal operator which then skips the part of the function that was mutated. Thia made me realise the imnportance of having a strong test case.

def weak_oracle(fn):
    assert fn(1, 1, 1) == 'Equilateral'

    assert fn(1, 2, 1) != 'Equilateral'
    assert fn(2, 2, 1) != 'Equilateral'
    assert fn(1, 2, 2) != 'Equilateral'

    assert fn(1, 2, 3) != 'Equilateral'

Use-Case

It is important in chasten that we implement new techniques that we learn throughout this course whether it be for test cases or implemeting source code. The more you can make software sustainable and bug-free the better. We should be aiming to learning new ways to do cerain tasks while reading through our books and then transferring that knowledge into our project.

Week 7

SE5

Summary

The chapter “Engineering for Equity” discusses the importance of equity and inclusivity in software engineering and talks about the challenges and failures that derive from biases. It emphasizes the importance of building products that work for a diverse user base and addressing biases that can affect software design and decision-making. The text also provides several examples of failures, such as Google’s image recognition issues and challenges in facial recognition technology.

Reflection

Reading this chapter I personally havent experienced biases with software but I have heard of or seen instances of it happening. I think as a software engineer it is important to realze how much power you have and how much influence you have as well. A tool that is implemented can shape a whole person well being and make them feel a certain type of way because of their experience with said tool or software.

Use-Case

When relating this to our project chasten. I think that a bias that is currently used when working with chasten is the fact that the program only works for python source code as of right now. What happens when someone tries to use our program with a C based language or JavaScript? I think that can be a bias that we would have to fix in the future.

FB5

Summary

“Mutation-Based Fuzzing” goes over just that, a testing technique that test inputs that can be considered valid for the software. These inputs can include different types of data like files, network packets, or command-line arguments. The inputs are then mutated slightly to keep the input valid, yet exercise new behavior. An example is seen below:

def delete_random_character(s: str) -> str:
    """Returns s with a random character deleted"""
    if s == "":
        return s

    pos = random.randint(0, len(s) - 1)
    # print("Deleting", repr(s[pos]), "at", pos)
    return s[:pos] + s[pos + 1:]

seed_input = "A quick brown fox"
for i in range(10):
    x = delete_random_character(seed_input)
    print(repr(x))

In the function above you see that a random character is deleted from the string every time its ran. This is what the output looks like:

'A uick brown fox'
'A quic brown fox'
'A quick brown fo'
'A quic brown fox'
'A quick bown fox'
'A quick bown fox'
'A quick brown fx'
'A quick brown ox'
'A quick brow fox'
'A quic brown fox'

Reflection

The purpose of mutation based analysis is to discover bugs, vulnerabilities, and unexpected behavior in a program, but the main thing this type of testing finds is vulnerbalitlties. By mutating inputs then running the program, if crashes were to occur then an indiction of potential vulnervalieties can considered or even if crashes were not to occure then vunerabilities can be detected depending on the expected output.

Use-Case

When working with chasten I think some fo the tools like integrate and datasette can incorpaorate mutation based fuzzing when running tests because I know that the input to run those command require different file paths that can be mutated.

Week 8

SE6

Summary

The chapter “How to Lead a Team” first dives into the two different leadership roles, a mangaer and a tech lead. These are two different leadership roles that are important to a team simultameously. The text aslo highlights servant leadership which is the concept of striving to create an atmosphere of humility, respect, and trust. It also is serving the needs of others and the well-being of the team or organization. “Antipatterns” are also discussed, which are patterns that managers should avoid at all cost. Some patterns include hiring people that can be controlled and manipulated easily, not adressing team members that seem to be struggling technically, or ignoring the overall personal needs of the team.

Reflection

Managers and tech leads require a different set of skills. Now can you be both, yes you can, but a manager is more of a person that can lead people and set up plans to get tasks done. A tech lead is a person that can lead engineering efforts and help assist with different software implementations. I categorize myself as a little bit of both but more of a tech lead, because once I fully understand an area I lead engineering efforts and help assist with different software implementations in that area.

Use-Case

As a team I think we have a number of people that are willing to take charge and be managers at times, and as the semster goes on, more and more people are getting more comfortable leading class. The problem that we run into is that we one dont have an abundance of tech leads, but too, we are not activley working in the same environment when working on the project. I think if we had class time where we could actively communicate with everyone and share our issues and knowledge, we would be better off.

FB6

Summary

The “Chapter fuzzing with Grammar” encovers grammar-based fuzzing, which is an approach to automated software testing. This approach involes generating wide ranges of valid inputs that follow a specific grammar. A grammer is basically a set of rules that the syntax of your input data is based on. This is an example of a grammer:

CGI_GRAMMAR: Grammar = {
    "<start>":
        ["<string>"],

    "<string>":
        ["<letter>", "<letter><string>"],

    "<letter>":
        ["<plus>", "<percent>", "<other>"],

    "<plus>":
        ["+"],

    "<percent>":
        ["%<hexdigit><hexdigit>"],

    "<hexdigit>":
        ["0", "1", "2", "3", "4", "5", "6", "7",
            "8", "9", "a", "b", "c", "d", "e", "f"],

    "<other>":  # Actually, could be _all_ letters
        ["0", "1", "2", "3", "4", "5", "a", "b", "c", "d", "e", "-", "_"],
}

As you can see, the key in this dictionary is the “symbol”. The symbol can be defined only once within a dictionary. Using the simple grammer fuzzer method, we can produce random valid inputs like this:

print("valid inputs")
for i in range(10):
    print(simple_grammar_fuzzer(grammar=CGI_GRAMMAR, max_nonterminals=10))

valid inputs
+%9a
+++%ce+
+_
+%c6c
++
+%cd+5
1%ee
%b9%d5
%96
%57d%42

Reflection

Reading through this chapter of fuzzingbook I recalled working with grammars before in cmpsc201, specifically with interpreters. So it was refreshing to see concepts that we learned before used in a different type of software engineering area. Nonetheless, I think this approach too software testing is important because it allows for automated generation of test cases with a wide variety of different inputs. This willhelp find vulnerabilities that might not get found with user generated test cases.

Use-Case

I think this approach to testing can be useful in the developmental project chasten. Specifically with testing xpath expressions with different xpath versions. A grammer can be made to randomly generate valid xpath expressions and feed them into different xpath parsers.

Week 9

SE7

Summary

This chapter “Leading at Scale”, piggey backs off the last chapter “How to lead a Team” to an extent. This chapter talks about how to be effective and efficient further along the path of leadership. Last chapter talked about stepping in to a leadership role from a individual contributor. The main points of this chapter revolves around the “Three Always of leadership”: Always Be Deciding, Always Be Leaving, Always Be Scaling.

Reflection

Reading the article I reflected on the three always of leadership and got a good understanding of each one. To me, always be deciding is important because as a leader you need to be able to manage your team but not micromanaging your team. It is not your role to solve specific engineering tasks but to identify the tradeoffs and constraints and put together an efficeint plan to get the task done. always be leaving stems from this idea as well. As a leader of an organization, you want to team to be able to self manage. It is your job as a leader to establish a culture in where your team members are progressively getting to that leadership role from that indivudal contributor role. Always be scaling is important as well because as a leader you need to make sure that deadlines are being met and issues are be solved with a good balance of quality and quantity.

Use-Case

I think so far the project devolpment of chasten has involed all three always of leadership. Because of the course design I think that it is important that the three always are incorportated during project development so that we can maximize our efficiency and effectivness when shipping new tools and updates chasten.

FB7

Summary

The chapter “Efficient Grammar Fuzzing” is a extension of chapter “Fuzzing with Grammar”. In this chapter, the downsides and vulnerablitles of the string based algorithm that was used in the last chapter are highleted. This chapter introduces the tree based algorithm, which is much faster and allows for much more control over the production of inputs that are generated by the fuzzing method. What we call a derivation tree is used when performing the tree based algorithm. A derivation tree is a tree shaped representation of the structure of a string in the context of formal grammar. A derivation tree consists of nodes which have other nodes as their children. The tree starts with one node that has no parent; this is called the root node; a node without children is called a leaf.

Reflection

The reason why the simple_grammar_fuzzer() introduced in the recent chapter was seen as inefficient was because it had some key issues. One being the possibility of generating infinte expansions there for having an infitie loop. This is never good for any program. Another issue that arises is the fact that is searches throug th input that is already being generated to find expansions and this could lead to more runtime. Last issue is that it is harder to control. Inputs have little to know constraints and therfore have the possibility to genearate really long inputs or even infinitley long inputs.

Use-Case

Like previuosly mentioned in the use-case before in the previous chapter, I believe this method of testing would be useful for generation of xpath patterns or json files potentionally for testing. But with the the introduction to the tree based method I think this method becomes more realistic to implement into our project, being that is is more controllably and not completely random.

Week 10

SE8

Summary

The chapter “Styles Guides and Rules” covers the importance of set policies and boundaries when working with code. The chapter highlights rules and style guides specifically. Why do we need rules, how do we create rules, how can we change rules, and then apply said rules are all discussed in the text. As well as language style guides for rules, what they are and what goes into making one. All style guide rules fall under 3 categories. Rules to avoid dangers ,rules to enforce best practices, and rules to ensure consistency.

Reflection

As software projects grow in size and complexity, the establishment of a comprehensive set of style guides and rules becomes increasingly vital. These guidelines play a pivotal role in maintaining the structure of the code, preventing it from descending into chaos and ensuring ease of maintenance. Additionally, adhering to a predictable pattern in code simplifies the recognition and resolution of problems or errors during the debugging phase.

Use-Case

In chasten we have a set of automated test that help initiate a set of rules for our project development team to enact. I think it would be helpful to address all rules as a class to make sure every rule and policy is critical to the development of chasten and not hindering our progress more than it is helping.

FB8

Summary

The chapter discusses the use of grammars and parsers for generating and analyzing strings in a structured way. It introduces Parser classes, specifically Parsing Expression Grammar parsers and Earley parsers , which can efficiently parse strings based on specific grammar structures. The chapter also highlights the significance of formal parsers in handling structured input and demonstrates the limitations of ad hoc parsing approaches. It encourages the use of grammars and parsers to accurately analyze and generate strings, especially in scenarios involving complex data formats. This is an example of a ad hoc parser that parses a given CSV-like string and represent its structure as a derivation tree.

def simple_parse_csv(mystring: str) -> DerivationTree:
    children: List[DerivationTree] = []
    tree = (START_SYMBOL, children)
    for i, line in enumerate(mystring.split('\n')):
        children.append(("record %d" % i, [(cell, [])
                                           for cell in line.split(',')]))
    return tree

Reflection

When designing parsers, especially for complex languages, the derivation tree serves as an intermediate representation during the parsing process. Analyzing the tree can help identify parsing errors, ambiguity in the input, or the presence of unexpected structures. So that is why transforming an input string into a derivation tree is a useful technique.

Use-Case

I feel like in chasten it owuld be a little challenging to incorportate this technique but it could prove beneficial. Especially with the likes of differne txpath patterns that could be analyzed more specfically and precisely.;

Week 12

SE9

Summary

In this section of the software engineering chapter at Google, the focus is on code review, a process where code is examined by someone other than its author, typically before it gets integrated into the codebase. Google employs a dedicated tool called “Critique” to facilitate this process, and they follow a structured six-step approach for code review:

1.The author makes changes to the code in their workspace and generates a summary of the modifications. 2.The author has the option to utilize automated comments or perform a self-review. 3.Reviewers inspect the modified code using the code review tool and provide comments on the changes. 4.Based on the feedback received, the author revises the code and uploads a snippet of the changes for reevaluation. 5.Reviewers thoroughly examine the code to ensure satisfaction and express approval. 6.Once approved, the author is granted permission to upload the changes.

Reflection

code review is important in software engineering because it allows for potential bugs, logic errors, or security vulnerabilities to be identified and addressed before the code is integrated into the codebase. It also allows for team members to share knowledge through review.

Use-Case

In chasten we have a built in review tracker using github that allows for TLs and students to approve changes to the main branch whether it be new code or added documentation. I think this process is well designed already and allows for code review to take place.

FB9

Summary

In this section of the fuzzing book, the concept of Delta Debugging is presented as a method for identifying specific sections of faulty code. Through a systematic process of selectively trimming or eliminating portions of an input, it becomes possible to pinpoint the precise location where a failure occurs. This approach allows us to form hypotheses about the reasons behind the failure based on the isolated segments of the input that trigger the issue. Here is an example of Delta Debugging:

class DeltaDebuggingReducer(CachingReducer):
    """Reduce inputs using delta debugging."""

    def reduce(self, inp: str) -> str:
        """Reduce input `inp` using delta debugging. Return reduced input."""

        self.reset()
        assert self.test(inp) != Runner.PASS

        n = 2     # Initial granularity
        while len(inp) >= 2:
            start = 0.0
            subset_length = len(inp) / n
            some_complement_is_failing = False

            while start < len(inp):
                complement = inp[:int(start)] + \
                    inp[int(start + subset_length):]

                if self.test(complement) == Runner.FAIL:
                    inp = complement
                    n = max(n - 1, 2)
                    some_complement_is_failing = True
                    break

                start += subset_length

            if not some_complement_is_failing:
                if n == len(inp):
                    break
                n = min(n * 2, len(inp))

        return inp

Reflection

The Delta Debugging algorithm works like a detective. It keeps making the problem smaller by looking at parts of it and checking if there’s still a mistake. It smartly changes how closely it looks at the problem, so it quickly finds the tiniest part that’s causing the issue. It’s like solving a puzzle, getting rid of pieces until you figure out which one is causing the problem.

Use-Case

Reducing Failure-Inducing Inputs can help multiple facets of both the cellveyor and chasten teams in terms of debugging. For example, it can pinpoint any path or xpath pattern that is faulty and show the coder what exactly is causing the failure. Which will speed up the debugging process.

Week 13

SE10

Summary

Documentation is the main ocal part for this chapter. Even though the benefits of documentation might not be obvious right away, it’s a crucial task for developers. They highlight the idea of making documentation easy for readers. Documentation is likened to code, necessitating management and editing procedures similar to those applied to actual code. This implies that documentation is susceptible to various processes, including addressing issues, handling pull requests, accommodating feature requests, and most notably, addressing bugs.

Reflection

Documentation is a really vital area of software enginnerring. Having clear informative documentation will allow for team members whether old or new to jump right in to your implementation and get a good idea of what is going on already. This will make it easier for them to improve or edit existing code. Documentation can also help users with actually using a tool that you and your team have imlplemented. If users are not able to use your tool from flaky documentation then what was the point of implementing it?

Use-Case

I know I am a culprit of this, but it is important to add additional documentation when implementing new code inside of chasten. There is no poertry check for this so it is easy to finsih code and then having a passing build and think you are done, but having documentation will be very helpful for team members who are searching through your implementation.

DB1

Summary

The chapter helps you learn by explaining how the function works, testing it with examples, finding a problem with handling quotes in HTML tags, and step-by-step fixing the code. To do this, it shows you a visual representation of how the code works and suggests making changes in an organized way to solve the problems.

The chapter also talks about methods that don’t work well for fixing issues, like using print statements everywhere, randomly changing code until it works, or making simple fixes that don’t really solve the main problem. It stresses the importance of really understanding the code, fixing the main problems, and using a systematic way of debugging.

Reflection

For me, Im someone that I like to search the internet for different instances of the same issues, ie. Stack Oveflow, but sometimes issues are unique and havent really been resolved before. So it is important that you understand what being tested because it will make it easier to try and come up with a hypothesis as to what is bugged.

Use-Case

Nothing really technical that could be applied to our working development teams, but insight for sure on how to go about debugging issues so that debugging can be more proficient and efficient.

Week 14

SE11

Summary

In the chapter “Testing Overview”, the importance of testing is discussed. Testing has always been important in coding, and it used to be something people did only manually. But now, we can automate tests, which makes it easier for software engineers to make changes to their code quickly. Google categorizes tests into three sizes: small, medium, and large. Small tests are those that operate independently without interacting with other processes. Medium tests have the capability to run on multiple threads, interact with web requests, and make various types of blocking calls. Large tests span across multiple machines, and there are fewer restrictions on what they can do.

Reflection

Testing is valuable as it can be used to sense vulnerabilties and bugs within code. It acts as a sense of security to programs. As it is important to have test cases,, you dont want test cases that fail or break builds because that would be doing more harm then little. That is why it is important to have majority smaller test cases that can test a specific output and not a large scale. The larger the test case the flkier it gets or the more risky it gets to pottentialy breaking the tool.

Use-Case

Not a lot of us have actually imlplemented test cases before in this instance per say, so I think it would be helpful if we go some examples or just a guide on how to write test cases and how they should look. I think this would increase everyones confidence on actually writing test cases and in result produce more, which we need, so that we have a good coverge of our tools.

DB2

Summary

The chapter of debugging book discusses the concept of tracing executions in Python for the purpose of debugging. It introduces a Tracer class that allows developers to log events during program execution and customize tracing as needed. The text covers various aspects, such as accessing source code, tracing calls and returns from functions, and monitoring variable changes. The Tracer class is extended to display the source code of the function being tracked, report function calls and returns, and highlight variable changes. Here is an example of the tracit function, a function to trace the execution of a Python program.

def traceit(frame: FrameType, event: str, arg: Any) -> Optional[Callable]:  # type: ignore
    if 'c' in frame.f_locals:
        value_of_c = frame.f_locals['c']
        print(f"{frame.f_lineno:} c = {repr(value_of_c)}")
    else:
        print(f"{frame.f_lineno:} c is undefined")

    return traceit

It is designed to be called at each line of code execution.

Reflection/Use-Case

Tracing executions is a versatile method that aids in different areas of software engineering. It assists in debugging, enhancing performance, conducting tests, analyzing security, and transferring knowledge within the development process.

Week 15

SE12

Summary

This chapter explains unit testing as a practice that focuses on testing specific functionalities within a larger program. Unlike broader tests, unit tests target the smallest functional “units.” A common pitfall in unit testing is creating brittle tests, which are easily broken by minor changes. These tests often depend on hardcoded attributes like data types or namespaces. The chapter highlights an example of testing a public API where developers may be tempted to access private members directly. Instead, the book suggests testing from an end user’s perspective to establish explicit contracts. If such a test breaks, it indicates potential issues for existing users of the system.

Reflection

Unit tests play a crucial role in early bug detection during development. By concentrating on specific functionalities, they enable the identification and resolution of issues before they can escalate into more significant problems.

Use-Case

Unit test are realy simple and easy to implement and they target specific outputs for functions that can be used to debug programs. This is something can prove useful for both the chasten and cellveyor teams.

DB3

Summary

The chapter “Assertions” in Debuggingbook, discusses the importance of assertions in software engineering, particularly in the context of debugging and ensuring code correctness. Assertions are statements that specify certain conditions expected to be true at runtime, and they play several crucial roles. assertions contribute significantly to the reliability, maintainability, and efficiency of software systems by automating checks, providing documentation, and aiding in the debugging process. Here is an simpl examplle function that uses an assert statement:

>>> def my_square_root(x):  # type: ignore
>>>     assert x >= 0
>>>     y = square_root(x)
>>>     assert math.isclose(y * y, x)
>>>     return y

Reflection/Use-Case

Assertions are like safety checks in computer programs. They’re helpful for finding mistakes early on, documenting how the code is supposed to work, and making sure things stay reliable and easy to manage. They act as a kind of security guard to catch problems before they cause bigger issues, and they also help teams work together better by making sure everyone understands how the code is supposed to behave. In simple terms, assertions are a key part of keeping software in good shape. Assertions are already being implemted to our chasten tests and are proving very helpful.

Week 16

DB4

Summary

This chapter highlights methods and concepts for statistical debugging, which involves linking specific events like covered code lines with both successful and unsuccessful results. Statistical debugging works by connecting bugs with specific behaviors or features in a program. It involves gathering details about how the program runs, like values of variables, functions used, or the order of actions. After collecting this data, statistical analysis is applied to recognize patterns linked to the existence of bugs. Here is an example of a class designed to track and record information about covered locations during the execution of a program.

class CoverageCollector(Collector, StackInspector):
    """A class to record covered locations during execution."""

    def __init__(self) -> None:
        """Constructor."""
        super().__init__()
        self._coverage: Coverage = set()

    def collect(self, frame: FrameType, event: str, arg: Any) -> None:
        """
        Save coverage for an observed event.
        """
        name = frame.f_code.co_name
        function = self.search_func(name, frame)

        if function is None:
            function = self.create_function(frame)

        location = (function, frame.f_lineno)
        self._coverage.add(location)

Reflection

Statistical debugging is valuable because it addresses the challenges posed by large codebases, enhances the efficiency of bug detection, provides insights into program behaviors, supports data-driven decision-making, complements traditional debugging methods, and contributes to continuous improvement in software development.

Use-Case

Statistical debugging is like having a special tool to find and fix mistakes in big and complicated computer programs. Imagine if you had a really huge puzzle, and instead of looking at each piece one by one, you use a smart method to see which pieces are most likely to be part of a problem. Statistical debugging does something similar for computer programs. It helps developers understand how the program behaves and where mistakes might be hiding. This way, they can find and fix the issues faster, especially when dealing with large and complex code. Our development teams could incorporate this technique for debugging, but ultimatley would have to decide as a team if implementing this type of code would be necessary for our tools chasten and cellveyor specfically. It might prove to be more benefical in the future though, as our code becomes more and more complex.