50、软件开发与质量保证:从实践到理论的深度剖析

软件开发与质量保证:从实践到理论的深度剖析

1. 系统开发中的技术实践

在软件开发过程中,我们会遇到各种实际问题,通过具体的技术手段来解决这些问题是提升系统质量的关键。

首先,在HTML表单加载时, $formfunc Smarty变量起着重要作用。它存储了一个JavaScript函数的名称,这个函数会在HTML表单加载时执行。 onload 表单属性会被设置为 $formfunc ,若 $formfunc 未定义则为空字符串。这样做的好处是,在加载过程中可以有选择地重新计算整个电子表格,使得 daycalc() 函数只需关注其所在的列、行和总计,而无需在每次按键时重新计算每个单元格。

然而,客户反馈“里程数”在屏幕上似乎无法正确持久化。这是因为它是元数组的例外情况,在 parse() 函数中未得到处理。为了解决这个问题,我们需要进行测试并修改代码。

测试代码如下:

function testParsingNbrMiles() {
    $this->_session->getDatabaseHandle()->query("delete FROM
                     travel_expense_item WHERE emp_id = 1 and
                     expense_date >= '1980-01-06' and expense_date
                      <= '2001-09-15'");
    $response = array ('mitr_sun' =>  "1.1",
                       'mitr_mon' =>  "2.2");
    $week = new TravelExpenseWeek (
        array ('emp_id' => "1", 
               'week_start' => "1980-01-06",
               'territory_worked' =>  "Midwest",
               'comments'         =>  "comment",
               'cash_advance'     =>  "0",
               'mileage_rate'     =>  "0.31"),
        $this->_session->getDatabaseHandle());
    $week->parse($response);
    $this->assertEquals(true, $week->persist());
    $week = new TravelExpenseWeek (
        array ('emp_id'           =>  "1", 
               'week_start' => "1980-01-06",
               'territory_worked' =>  "Midwest",
               'comments'         =>  "comment",
               'cash_advance'     =>  "0",
               'mileage_rate'     =>  "0.31"),
        $this->_session->getDatabaseHandle());
    $week->readWeek();

    $this->assertEquals(1.1, (float) $week->getExpenseAmount(0, 
                        'trans_miles_traveled'));
    $this->assertEquals(2.2, (float) $week->getExpenseAmount(1,
                        'trans_miles_traveled'));     
}

同时,需要对 TravelExpenseWeek 类中的代码进行修改:

private function createByRequest ($description, $daynum,
                                 $index,  & $request) {
    if (array_key_exists($index, $request) and
        $request[$index] <> null and
        $request[$index] <> "") {
        array_push (
            $this->items,
            new TravelExpenseItem (
                array ('emp_id'       => $this->emp_id,
                       'expense_date' => 
                       $this->addDays($this->week_start, $daynum),
                       'description'  => $description,
                       'amount'       => (float) $request[$index]),
                $this->dbh));
    }
}

public function parse( & $request) {
    foreach ($this->getExpensesMetaArray() as $sectionlist) {
        for ($i=0; $i < count ($sectionlist['persist']); $i++) {
            $daynum = 0;
            foreach ($this->getWeekArray() as $day) {
                $index = $sectionlist['code']."_".$day."_".$i;
                $this->createByRequest (
                    $sectionlist['persist'][$i], $daynum,
                    $index, $request);
                $daynum++;
            }
        }
    }
    // arg, mitr is an exception
    $daynum = 0;
    foreach ($this->getWeekArray() as $day) {
        $this->createByRequest ("trans_miles_traveled", $daynum,
                                "mitr_".$day, $request); 
        $daynum++;
    }
}

新的 TravelExpenseWeek - createByRequest() 函数避免了代码重复,因为它在正常处理和里程处理时都会被调用。当所有测试通过,客户满意,屏幕正常工作时,“费用报告作为电子表格”这个任务就完成了。

2. 模拟对象在测试中的应用

在测试过程中,有时会遇到无法在测试环境中访问确定性对象的情况。例如:
- 真实对象是非确定性的,如实时股票或天气数据。
- 真实对象对于测试套件来说太慢,如过载的事务性生产数据库。
- 需要测试异常情况,如入侵警报或系统故障。
- 真实对象不存在,可能是无法访问所需对象或缺乏必要的对象内部功能。

模拟对象是一种可以模拟足够功能或所需功能的对象,用于全面测试系统。例如,若要测试会话超时、错误或恶意破解,可以导入 mock - widgetsession.phpm ,代码如下:

class MockWidgetSession extends WidgetSession {
    public function getUserObject() {
        return new WidgetUser(
            array (
                'id' => 1,
                'username' =>  'ed',
                'md5_pw' => "827ccb0eea8a706c4c34a16891f84e7b",
                'first_name' => "Ed",
                'last_name' => "Lecky-Thompson",
                'email' => "ed@lecky-thompson.com",
                'role' => "s",
                'department' => "sales"
            )
        );
    }
}

这个 MockWidgetSession 示例可以让测试环境模拟登录。此外,Smarty还可用于模拟HTML屏幕,将HTML保存到变量中进行处理。

3. 电子邮件测试与相关函数

以销售经理通知的任务为例,需要在保存联系人时向经理发送电子邮件。为了测试这个功能,我们有如下测试代码:

function testContactEmail () {
    $u = new WidgetUser(
        array ('id' => 1,
               'username'   => "ed",
               'first_name' => "Ed",
               'last_name'  => "Lecky-Thompson",
               'email'      => "ed@lecky-thompson.com",
               'role'       => "s",
               'department' => "sales"));
    $cv = new ContactVisit (
        array ('emp_id'             => "1", 
               'week_start'         => "1980-01-01",
               'company_name'       => "test one",
               'contact_name'       => "Big One",
               'city'               => "Columbus",
               'state'              => "OH",
               'accomplishments'    => "phone call",
               'followup'           => "",
               'literature_request' => ""));
    $c = new Contact (
        array ("emp_id"             => "1", 
               "week_start"         => "1980-01-01",
               "shop_calls"         => 2,
               "distributor_calls"  => 3,
               "engineer_calls"     => 4,
               "mileage"            => 50,
               "territory_worked"   => "Central Ohio",
               "territory_comments" => "Buckeyes are great." ),
        $this->_session->getDatabaseHandle());

    list ($email,$from, $subject, $message, $headers) =
        generateContactEmail($u, $c, array ($cv), false);

    // test screen capture, requires 7bit ascii encoding (read: none)
    $this->assertEquals(1, preg_match ("/Employee Name..............Ed
                        Lecky-Thompson/", $message), "employee name");
    $this->assertEquals(1, preg_match("/company_name_0.
                        ....................test one/", $message),
                        " company name " );
    $this->assertEquals(1, preg_match ("/shop_calls..................
                        ...............2/", $message),"shop calls");
    $this->assertEquals(1, preg_match ("/To: ed@lecky-thompson.com/",
                        $headers),"email");

    // test base64 encoding
    list ($email_from, $subject, $message, $headers) =
              generateContactEmail($u, $c, array ($cv));

    $this->assertEquals(0, preg_match ("/Employee Name......
                        ........Ed Lecky-Thompson/", $message),
                        "employee name");
    $this->assertEquals(1, preg_match ("/To: ed@lecky-thompson.com/",
                        $headers),"email");
}

generateContactEmail() 函数用于返回PHP mail() 函数所需的参数: mail($email_address, $subject, $message, $headers); 。在这个示例中,我们测试浏览器看到的内容,通过正则表达式确保表单包含预期信息。

相关函数如下:

function mimeifyContent ($content, $mime_boundary,
                         $filename, $flagBase64=true) {
    $message = "";
    $message .= " \r\n";
    $message .= "-".$mime_boundary."\r\n";
    $message .= "Content-Type: text/html;\r\n";
    $message .= " name=\"".$filename.".html\"\r\n";
    // default is 7bit ascii
    if ($flagBase64) {
        $message .= "Content-Transfer-Encoding: base64\r\n";
    }
    $message .= "Content-Disposition: attachment;\r\n";
    $message .= " filename=\"".$filename.".html\"\r\n";
    $message .= "\r\n";
    if ($flagBase64) {
        $message .= base64_encode($content);
    } else {
        $message .= $content;
    }
    $message .= "\r\n";
    return ($message);
}

function generateContactEmail ($user, $contact,
                               $contactVisits, $flagBase64=true) {
    global $GLOBALS;
    require_once ($GLOBALS["smarty-path"].'Smarty.class.php');     
    $smarty = new Smarty;
    $smarty->assign_by_ref ("user", $user);
    $smarty->assign_by_ref ("contact", $contact);
    $smarty->assign_by_ref ("contactVisits", $contactVisits);
    $smarty->assign('start_weeks', getStartWeeks());
    $smarty->assign('current_start_week', $contact->week_start);
    $smarty -> assign( "max_weekly_contacts", $GLOBALS[ "max - weekly - contacts" ]);
    $email_body = @$smarty->fetch('customer-contacts.tpl');
    $headers = "";
    $headers .= "From: ".$GLOBALS["email-from"]."\n";
    $headers .= "To: ".$user->email."\n";
    if (strlen ($GLOBALS["email-contact-cc"]) > 0)         
        $headers .= "Cc: ";
        $headers .= $GLOBALS["email-contact-cc"];
    $headers .= "\n";
    if (strlen ($GLOBALS["email-contact-bcc"]) > 0)
        $headers .= "Bcc: ".$GLOBALS["email-contact-bcc"]."\n";
    $mime_boundary = " < < < -==+X[".md5(time())."]";
    $headers .= "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: multipart/mixed;\r\n";
    $headers .= " boundary=\"".$mime_boundary."\"";
    $message = "";
    $message .= "This is a multi-part message in MIME format.\r\n";
    $message .= "\r\n";
    $message .= "-".$mime_boundary."\r\n";
    $message .= "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n";
    $message .= "Content-Transfer-Encoding: 7bit\r\n";
    $message .= "\r\n";
    $message .= $GLOBALS["email-contact-message"]."\n\n";
    $nextEnding = "\r\n";
    $message.=mimeifyContent($email_body,$mime_boundary,
                              "customer-contact", $flagBase64);
    $message.="-".$mime_boundary."".$nextEnding;
    $subject = $user->emp_id." ".$user->last_name." : ".$user->email_subject;
    return array ($user->email, $subject, $message, $headers);
}

这里需要注意两点:一是调用 $smarty->fetch() 而不是 $smarty->display() fetch 函数将HTML输出保存到变量中;二是为避免非7位ASCII字符问题,可对HTML输出进行base64编码,但这会使测试变得困难,因此有 $flagBase64 参数。

4. 软件开发原则与质量保证的重要性

软件开发不仅仅是让代码“运行起来”,更重要的是构建一个经过充分测试且具有可扩展性的系统。测试驱动开发在软件开发中起着至关重要的作用,它不仅能帮助开发代码,还能发现漏洞,并在系统的不同部分进行持续测试。

重构也不是简单的“代码清理”,它应成为软件开发过程中的一个编码优先级。持续重构有助于开发复杂的框架,而无需进行过多的分析和添加未使用的功能。

极端编程(XP)的一些原则,如测试和持续重构,可以降低开发的复杂性,保持代码库的灵活性和敏捷性。虽然不是每个项目都适合采用完整的XP方法,但其他开发方法也可以从中受益。

然而,无论在构建过程中多么有条理和勤奋,都不能跳过项目中最重要的部分——质量保证。

5. 质量保证的必要性

在软件开发中,即使项目看起来进展顺利,如Widget World销售自动化工具包网站按计划进行且预算合理,客户端对开发环境和暂存服务器上的测试版本也满意,但此时仍不能放松警惕。

质量保证是从传统制造业和工程流程中借鉴而来的概念,对于复杂而关键的应用程序同样适用。

目前,普通用户对网络和互联网可靠性的期望仍然较低。例如,客户可能会遇到电子邮件故障、在线购物时信用卡处理中断、ISP服务中断等问题,但往往选择接受。这主要有两个原因:一是人们认为互联网本身复杂,出现问题是正常的,但实际上互联网的底层基础设施是相当稳定的,问题往往出在程序员编写的糟糕代码和开发时做出的错误决策;二是许多人有过与互联网应用开发者合作的糟糕经历,导致对当前供应商的期望极低。

但我们不应该因为客户期望低而降低目标。在交付产品前追求高质量,不仅能让客户满意,也能让开发者保持良好的工作状态。采用系统的质量保证方法在交付前有以下好处:
- 通过全面、结构化的方法,将解决缺陷所花费的开发时间和成本降至最低。
- 确保团队能及时过渡到其他项目。
- 能将部署过程中遇到的问题与应用程序本身区分开来。

6. 质量保证的实施步骤

为了确保软件的质量,我们可以按照以下步骤进行质量保证:
1. 需求分析与规划 :明确项目的需求和目标,制定详细的质量保证计划,包括测试范围、测试方法、测试时间安排等。
2. 单元测试 :对系统的各个独立组件进行测试,确保每个组件的功能正确。例如,在前面提到的代码中,对 testParsingNbrMiles testContactEmail 等测试用例的编写和执行。
3. 集成测试 :将各个组件集成在一起进行测试,检查组件之间的交互是否正常。
4. 系统测试 :对整个系统进行全面测试,模拟真实的使用场景,确保系统在各种情况下都能正常运行。
5. 用户验收测试 :让最终用户参与测试,根据用户的反馈进行调整和优化。

7. 总结

软件开发是一个复杂的过程,涉及到技术实践、测试方法、开发原则和质量保证等多个方面。通过具体的技术手段解决实际问题,运用模拟对象进行测试,遵循软件开发原则,以及实施有效的质量保证措施,我们可以开发出高质量、可靠的软件系统。在未来的开发中,我们应该不断学习和实践,提高自己的开发能力和质量意识,为用户提供更好的软件产品。

以下是一个简单的质量保证流程的mermaid流程图:

graph LR
    A[需求分析与规划] --> B[单元测试]
    B --> C[集成测试]
    C --> D[系统测试]
    D --> E[用户验收测试]
    E --> F[交付使用]

通过这个流程图,我们可以清晰地看到质量保证的各个阶段及其顺序,有助于我们在实际开发中更好地实施质量保证措施。

软件开发与质量保证:从实践到理论的深度剖析

8. 测试类型与重点关注

在质量保证过程中,不同类型的测试有着各自的重点和作用。
- 功能测试 :主要验证系统的各项功能是否符合需求规格说明书。例如,在前面提到的费用报告系统中,要确保“里程数”的输入、计算和持久化功能正常,以及电子邮件通知功能能够准确发送包含正确信息的邮件。
- 性能测试 :评估系统在不同负载下的性能表现,如响应时间、吞吐量等。对于可能处理大量数据的销售自动化工具包网站,需要测试其在高并发情况下的性能,避免出现系统变慢或崩溃的情况。
- 安全测试 :检查系统的安全性,防止数据泄露、恶意攻击等。包括对用户登录认证、数据传输加密等方面的测试。
- 兼容性测试 :确保系统在不同的浏览器、操作系统和设备上都能正常运行。例如,要测试网站在Chrome、Firefox、Safari等主流浏览器,以及Windows、Mac OS、iOS和Android等不同操作系统上的显示和功能是否一致。

以下是一个测试类型及其重点的表格:
| 测试类型 | 重点关注 |
| ---- | ---- |
| 功能测试 | 系统功能是否符合需求 |
| 性能测试 | 系统在不同负载下的性能表现 |
| 安全测试 | 系统的安全性,防止数据泄露和攻击 |
| 兼容性测试 | 系统在不同环境下的运行情况 |

9. 质量保证团队的协作

质量保证不仅仅是测试人员的工作,而是整个团队的责任。在软件开发过程中,各个角色需要密切协作,共同确保软件的质量。
- 开发人员 :编写高质量的代码,进行单元测试,及时修复发现的缺陷。在开发过程中,遵循良好的编码规范和设计原则,提高代码的可维护性和可测试性。
- 测试人员 :制定测试计划,执行各种类型的测试,记录和跟踪缺陷。与开发人员密切沟通,确保缺陷得到及时解决。
- 产品经理 :明确产品需求,与开发和测试团队共同确定测试范围和重点。在项目过程中,及时反馈用户需求的变化,确保产品的功能和质量符合用户期望。
- 项目经理 :协调团队资源,制定项目计划,监控项目进度和质量。在项目出现问题时,及时组织团队进行解决,确保项目按时交付。

以下是一个团队协作的mermaid流程图:

graph LR
    A[开发人员] <--> B[测试人员]
    A <--> C[产品经理]
    B <--> C
    A & B & C <--> D[项目经理]
10. 持续改进与质量文化建设

质量保证是一个持续的过程,需要不断地进行改进和优化。在项目结束后,团队应该对整个开发过程进行回顾和总结,分析存在的问题和不足之处,制定改进措施。
- 缺陷分析 :对发现的缺陷进行分类和统计,分析缺陷产生的原因,如代码逻辑错误、需求理解偏差、测试覆盖不足等。根据分析结果,采取相应的措施进行改进,如加强代码审查、完善需求文档、增加测试用例等。
- 流程优化 :评估项目的开发流程和质量保证流程,找出其中的瓶颈和薄弱环节,进行优化和改进。例如,缩短测试周期、提高缺陷修复效率等。
- 培训与学习 :为团队成员提供相关的培训和学习机会,提高他们的技术水平和质量意识。例如,组织测试技术培训、编码规范培训等。

建立质量文化也是非常重要的。团队成员应该树立质量第一的观念,将质量意识融入到日常工作中。通过激励机制和团队活动,鼓励团队成员积极参与质量保证工作,共同提高产品的质量。

11. 应对质量问题的策略

在质量保证过程中,难免会遇到各种质量问题。以下是一些应对质量问题的策略:
- 及时发现问题 :通过建立完善的测试体系和监控机制,及时发现系统中的缺陷和问题。例如,使用自动化测试工具进行持续集成和持续测试,及时发现代码变更引入的问题。
- 快速响应问题 :一旦发现问题,要及时组织团队进行分析和解决。建立快速响应机制,确保问题得到及时处理,避免问题扩大化。
- 深入分析问题 :对问题进行深入分析,找出问题的根源,而不仅仅是解决表面症状。通过根因分析,采取有效的措施防止问题再次出现。
- 预防问题发生 :通过总结经验教训,采取预防措施,避免类似问题在未来的项目中再次发生。例如,完善需求文档、加强代码审查、提高测试覆盖率等。

12. 质量保证的未来趋势

随着技术的不断发展,质量保证也面临着新的挑战和机遇。以下是一些质量保证的未来趋势:
- 自动化测试 :自动化测试将越来越普及,通过使用自动化测试工具和框架,可以提高测试效率和准确性。例如,使用Selenium进行Web应用的自动化测试,使用JUnit进行Java代码的单元测试。
- 人工智能与机器学习 :人工智能和机器学习技术将应用于质量保证领域,如缺陷预测、测试用例生成等。通过分析大量的历史数据,预测可能出现的缺陷,自动生成更有效的测试用例。
- DevOps与持续交付 :DevOps和持续交付的理念将更加深入人心,质量保证将贯穿整个软件开发的生命周期。通过自动化部署和持续集成,实现快速、可靠的软件交付。
- 云测试 :云测试将成为一种常见的测试方式,通过使用云平台提供的测试资源,可以降低测试成本,提高测试效率。

13. 总结与展望

质量保证是软件开发过程中不可或缺的一部分,它对于确保软件的质量和可靠性起着至关重要的作用。通过遵循软件开发原则,实施有效的质量保证措施,团队可以开发出高质量、可靠的软件系统。

在未来的软件开发中,我们应该不断关注质量保证的新技术和新方法,积极引入自动化测试、人工智能等技术,提高质量保证的效率和效果。同时,要加强团队协作,建立质量文化,持续改进质量保证流程,为用户提供更好的软件产品。

总之,质量保证是一个长期而持续的过程,需要我们不断地学习和实践,不断地提高自己的能力和水平,才能在激烈的市场竞争中立于不败之地。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值